使用smtplib

时间:2019-09-07 20:53:20

标签: python smtplib dkim

我正在尝试通过smtplib发送电子邮件,它们似乎运行良好。唯一的问题是DKIM失败,邮件通常直接进入垃圾邮件文件夹。

在我的共享主机上启用了DKIM(如果有帮助,主机是a2hosting),并且在使用Thunderbird发送单个电子邮件时,该过程运行良好,并且DKIM通过了,这表明问题出在我身上。

我什至尝试使用dkimpy使用私钥对电子邮件进行显式签名,但在ARC-Authentication-Results下仍然出现dkim = fail。 我提到的一些帖子和答案建议使用“登录”作为解决方案,但是我已经使用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仍然失败。

由于服务器回复“身份验证成功”,因此身份验证似乎没有问题

编辑:

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。预期的主体哈希和接收的主体哈希也匹配。我不确定是什么问题。

2 个答案:

答案 0 :(得分:3)

经过大量研究和暴力手段,我终于找到了解决我问题的方法。 我还需要在标题中包含Message-ID和日期。 在代码中添加以下行有助于我通过验证。

msg['Date'] = email.utils.formatdate()
msg['Message-ID'] = email.utils.make_msgid(domain='mydomain.tld')

答案 1 :(得分:0)

重要提示:您需要将您的 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