python3 禁用 base64 并删除 MIME 版本的电子邮件

python3 email message to disable base64 and remove MIME-Version

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==

你绝对不能删除 MIME-Version: header;它将此标识为 MIME 消息。

From: header 确实应该是 RFC2047 编码的,文档表明它将是“当消息被序列化时”。当你 print(msg) 你没有正确序列化它;你想要 print(msg.as_string()) 确实展示了所需的序列化。

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

在旧的 email 库中,需要各种技巧才能做到这一点,但在 Python 3.6 中引入的新 EmailMessage 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

不幸的是,从文档中弄清楚这一点几乎是不可能的。 The documentation for set_content basically just defers to the policy which obscurely points to the raw_data_manager(如果您甚至注意到 link)...最终您希望注意到 cte 关键字参数的存在。

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

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

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

在 body 文本中。)

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

为了您的娱乐,这里有一些关于 crazy hacks for Python 3.5 and earlier.

的老问题