使用 smtplib 发送邮件时 DKIM 失败
DKIM fails when sending mails with smtplib
我正在尝试使用 smtplib 发送电子邮件,它们似乎可以正常发送。唯一的问题是 DKIM 失败,邮件通常会直接进入垃圾邮件文件夹。
我的共享主机启用了 DKIM(主机是 a2hosting,如果有帮助的话),当使用 Thunderbird 发送个人电子邮件时,该过程工作正常,并且 DKIM 通过,表明问题出在我这边。
我什至尝试使用 dkimpy 使用私钥显式签署电子邮件,但在 ARC-Authentication-Results 下我仍然得到 dkim=fail。
我提到的一些帖子和答案建议 "logging in" 作为解决方案,但我已经使用 SMTP.login() 登录,正如我之前提到的,正在发送电子邮件。
我提到的一个答案提到,签署电子邮件是服务器的工作,值得一提的是原始电子邮件输出包括 DKIM 签名,即使没有使用 dkimpy 明确签署,表明服务器签署为预期。
但问题仍然存在,即 DKIM 失败会影响电子邮件的送达率,并且原始输出没有提供有关域的 DKIM 失败原因的任何详细信息。
我使用以下代码片段发送电子邮件
msg = MIMEMultipart()
msg['From'] = 'myemail@mydomain.tld'
msg['To'] = 'someemail@gmail.com'
msg['Subject'] = "Subject"
msg.attach(MIMEText("SomeText", "plain"))
s = smtplib.SMTP_SSL("mydomain.tld:465")
s.login("myemail@mydomain.tld", "mypassword")
s.sendmail("myemail@mydomain.tld", 'someemail@gmail.com',msg.as_string())
我试过如下签名消息
headers = ["To", "From", "Subject"]
with open("cert.pem") as fh:
dkim_private = fh.read()
sig = dkim.sign(
message=msg.as_string().encode("ascii"),
selector=str(dkim_selector).encode("ascii"),
domain="robogyan.tech".encode("ascii"),
privkey=dkim_private.encode("ascii"),
include_headers=headers,)
msg["DKIM-Signature"] = sig.decode("ascii").lstrip("DKIM-Signature: ")
原始输出确实反映了带有上述代码的签名,但 DKIM 仍然失败。
由于服务器回复了 "Authentication succeeded"
,因此身份验证似乎没有任何问题
编辑:
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
d=mydomain.tld; s=default; h=Subject:To:From:MIME-Version:Content-Type:
Sender:Reply-To:Date:Message-ID:Cc:Content-Transfer-Encoding:Content-ID:
Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:
List-Subscribe:List-Post:List-Owner:List-Archive;
bh=giCDGo/0duFr1Ex65l7Ixc3N45EAULK+gw5cHV8pO0k=; b=DR08Q+CjgOLqo8WkLJs/XROfTw
Z7+ph+qnzi5p49cT3+UwQolcL1CKIVPk7XRkL8WZ3FFa9hZuc6TumquRSiYd5uR0AC5Z3lopEfnQe
fdbOOTRnks2ZzoOnQusy/gmydUttypu8wTthFhy7vTWXMFcdI29X/HkrokCtiGKCoD2u2kWBtn2sm
3/aP83lBbMpcWsNbvo3HTsL71o8QPd6bVKpqRGyAy89cAwMLwP4dnJ9WcCxxNzowlJNPQja3o5W16
t3rG/KizcRehjaDUXhPPRF/4RdYUSIi/SGNwmIPwvkZNc17k3wQpszKeG6/Ujgax/i7Li7V7dLJBT
Fu/x6xDA==;
Signed-by: myemail@mydomain.tld
Expected-Body-Hash: giCDGo/0duFr1Ex65l7Ixc3N45EAULK+gw5cHV8pO0k=
如果有帮助,这是失败电子邮件的 DKIM。预期的正文哈希和接收到的正文哈希也匹配。我不确定那是什么问题。
经过大量研究和蛮力方法,我终于找到了解决问题的方法。
我还需要在 headers 中包含 Message-ID 和日期。
在代码中添加以下几行帮助我通过了验证。
msg['Date'] = email.utils.formatdate()
msg['Message-ID'] = email.utils.make_msgid(domain='mydomain.tld')
重要提示:您需要将 smtp 客户端的机器 IP 地址添加到 InternalHosts
列表中,因为 OpenDKIM 将使用 these rules.
检查客户端的权限
您需要将此行添加到您的 /etc/opendkim.conf
:
InternalHosts file:/etc/opendkim/TrustedHosts # or any location you want
/etc/opendkim/TrustedHosts
的内容可能如下所示:
127.0.0.1
::1
localhost
<server_ip>
hostname.example1.com
example1.com
hostname.example2.com
example2.com
...
这只是举例。您需要在此处输入您的 python smtplib-client 机器地址 (ip/host)。
然后重启你的 opendkim
:
$ sudo service opendkim restart
我正在尝试使用 smtplib 发送电子邮件,它们似乎可以正常发送。唯一的问题是 DKIM 失败,邮件通常会直接进入垃圾邮件文件夹。
我的共享主机启用了 DKIM(主机是 a2hosting,如果有帮助的话),当使用 Thunderbird 发送个人电子邮件时,该过程工作正常,并且 DKIM 通过,表明问题出在我这边。
我什至尝试使用 dkimpy 使用私钥显式签署电子邮件,但在 ARC-Authentication-Results 下我仍然得到 dkim=fail。 我提到的一些帖子和答案建议 "logging in" 作为解决方案,但我已经使用 SMTP.login() 登录,正如我之前提到的,正在发送电子邮件。
我提到的一个答案提到,签署电子邮件是服务器的工作,值得一提的是原始电子邮件输出包括 DKIM 签名,即使没有使用 dkimpy 明确签署,表明服务器签署为预期。
但问题仍然存在,即 DKIM 失败会影响电子邮件的送达率,并且原始输出没有提供有关域的 DKIM 失败原因的任何详细信息。
我使用以下代码片段发送电子邮件
msg = MIMEMultipart()
msg['From'] = 'myemail@mydomain.tld'
msg['To'] = 'someemail@gmail.com'
msg['Subject'] = "Subject"
msg.attach(MIMEText("SomeText", "plain"))
s = smtplib.SMTP_SSL("mydomain.tld:465")
s.login("myemail@mydomain.tld", "mypassword")
s.sendmail("myemail@mydomain.tld", 'someemail@gmail.com',msg.as_string())
我试过如下签名消息
headers = ["To", "From", "Subject"]
with open("cert.pem") as fh:
dkim_private = fh.read()
sig = dkim.sign(
message=msg.as_string().encode("ascii"),
selector=str(dkim_selector).encode("ascii"),
domain="robogyan.tech".encode("ascii"),
privkey=dkim_private.encode("ascii"),
include_headers=headers,)
msg["DKIM-Signature"] = sig.decode("ascii").lstrip("DKIM-Signature: ")
原始输出确实反映了带有上述代码的签名,但 DKIM 仍然失败。
由于服务器回复了 "Authentication succeeded"
,因此身份验证似乎没有任何问题编辑:
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
d=mydomain.tld; s=default; h=Subject:To:From:MIME-Version:Content-Type:
Sender:Reply-To:Date:Message-ID:Cc:Content-Transfer-Encoding:Content-ID:
Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:
List-Subscribe:List-Post:List-Owner:List-Archive;
bh=giCDGo/0duFr1Ex65l7Ixc3N45EAULK+gw5cHV8pO0k=; b=DR08Q+CjgOLqo8WkLJs/XROfTw
Z7+ph+qnzi5p49cT3+UwQolcL1CKIVPk7XRkL8WZ3FFa9hZuc6TumquRSiYd5uR0AC5Z3lopEfnQe
fdbOOTRnks2ZzoOnQusy/gmydUttypu8wTthFhy7vTWXMFcdI29X/HkrokCtiGKCoD2u2kWBtn2sm
3/aP83lBbMpcWsNbvo3HTsL71o8QPd6bVKpqRGyAy89cAwMLwP4dnJ9WcCxxNzowlJNPQja3o5W16
t3rG/KizcRehjaDUXhPPRF/4RdYUSIi/SGNwmIPwvkZNc17k3wQpszKeG6/Ujgax/i7Li7V7dLJBT
Fu/x6xDA==;
Signed-by: myemail@mydomain.tld
Expected-Body-Hash: giCDGo/0duFr1Ex65l7Ixc3N45EAULK+gw5cHV8pO0k=
如果有帮助,这是失败电子邮件的 DKIM。预期的正文哈希和接收到的正文哈希也匹配。我不确定那是什么问题。
经过大量研究和蛮力方法,我终于找到了解决问题的方法。 我还需要在 headers 中包含 Message-ID 和日期。 在代码中添加以下几行帮助我通过了验证。
msg['Date'] = email.utils.formatdate()
msg['Message-ID'] = email.utils.make_msgid(domain='mydomain.tld')
重要提示:您需要将 smtp 客户端的机器 IP 地址添加到 InternalHosts
列表中,因为 OpenDKIM 将使用 these rules.
您需要将此行添加到您的 /etc/opendkim.conf
:
InternalHosts file:/etc/opendkim/TrustedHosts # or any location you want
/etc/opendkim/TrustedHosts
的内容可能如下所示:
127.0.0.1
::1
localhost
<server_ip>
hostname.example1.com
example1.com
hostname.example2.com
example2.com
...
这只是举例。您需要在此处输入您的 python smtplib-client 机器地址 (ip/host)。
然后重启你的 opendkim
:
$ sudo service opendkim restart