首页 > 解决方案 > 用于禁用 base64 并删除 MIME 版本的 python3 电子邮件

问题描述

from email.message import EmailMessage
from email.headerregistry import Address
msg = EmailMessage()

msg['From'] = Address("Pepé Le Pew", "pepe", "example.com")
msg['To'] = (
        Address("Penelope Pussycat", "penelope", "example.com")
        , Address("Fabrette Pussycat", "fabrette", "example.com")
        )
msg['Subject'] = 'This email sent from Python code'
msg.set_content("""\
        Salut!

        Cela ressemble à un excellent recipie[1] déjeuner.

        [1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718

        --Pepé
        """)
print(msg)

上面的代码生成使用 base64 编码的电子邮件。如何禁用它?如何删除 MIME-Version 字段?

接收者会正确解释“Pepé”的编码吗?如果不是,那么确保接收者正确解释其编码的正确方法是什么?

From: Pepé Le Pew <pepe@example.com>
To: Penelope Pussycat <penelope@example.com>,
 Fabrette Pussycat <fabrette@example.com>
Subject: This email sent from Python code
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
MIME-Version: 1.0

CQlTYWx1dCEKCgkJQ2VsYSByZXNzZW1ibGUgw6AgdW4gZXhjZWxsZW50IHJlY2lwaWVbMV0gZMOp
amV1bmVyLgoKCQlbMV0gaHR0cDovL3d3dy55dW1tbHkuY29tL3JlY2lwZS9Sb2FzdGVkLUFzcGFy
YWd1cy1FcGljdXJpb3VzLTIwMzcxOAoKCQktLVBlcMOpCgkJCg==

标签: pythonemailutf-8

解决方案


您绝对不能删除标题MIME-Version:;这就是将其标识为 MIME 消息的原因。

From:头确实应该是 RFC2047 编码的,并且文档建议它将是“当消息被序列化时”。当您print(msg)没有正确序列化它时;你想要print(msg.as_string())哪个确实表现出所需的序列化。

当涉及到传输编码时,Python 的email库对使用base64内容很不吸引人,这些内容很可能被编码为quoted-printable。您不能真正可靠地发送完全未编码的内容(尽管如果您愿意,MIME8bitbinary编码将能够适应这种情况;但为了向后兼容,SMTP 要求将所有内容编码为 7 位表示)。

在旧email库中,需要各种恶作剧才能做到这一点,但在EmailMessagePython 3.6 中引入的新 API 中,您实际上只需要添加调用cte='quoted-printable'即可。set_content

from email.message import EmailMessage
from email.headerregistry import Address

msg = EmailMessage()

msg['From'] = Address("Pepé Le Pew", "pepe", "example.com")
msg['To'] = (
        Address("Penelope Pussycat", "penelope", "example.com")
        , Address("Fabrette Pussycat", "fabrette", "example.com")
        )
msg['Subject'] = 'This email sent from Python code'
msg.set_content("""\
        Salut!

        Cela ressemble à un excellent recipie[1] déjeuner.

        [1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718

        --Pepé
        """, cte="quoted-printable")   # <-- notice added parameter
print(msg.as_string())                 # <-- properly serialize

不幸的是,从文档中弄清楚这一点几乎是不可能的。文档set_content基本上只是推迟到policy哪个模糊地指向raw_data_manager(如果你甚至注意到链接)......最后你希望注意到cte关键字参数的存在。

演示:https ://ideone.com/eLAt11

(顺便说一句,您可能还想

replace('\n   ', '\n')

在正文中。)

如果您使用8bitbinary内容传输编码,它们之间的区别在于前者有行长限制(最多 900 个字符),而后者完全不受限制。但是您需要确保整个 SMTP 传输路径是 8 位干净的(此时您不妨完全转向Unicode 电子邮件/ESMTP SMTPUTF8)。

为了您的娱乐,这里有一些关于 Python 3.5 及更早版本的疯狂 黑客 的老问题。


推荐阅读