简体   繁体   English

python3 email 消息禁用 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)

The above code produces an email message that uses base64 encoding.上面的代码产生一个使用 base64 编码的 email 消息。 How to disable it?如何禁用它? How to remove the field of MIME-Version?如何删除 MIME-Version 字段?

Will the encoding of "Pepé" be correctly interpreted by the recipient?接收者会正确解释“Pepé”的编码吗? If not, what is the correct way to ensure its encoding is interpreted by the recipient correctly?如果不是,那么确保接收者正确解释其编码的正确方法是什么?

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

You absolutely must not remove the MIME-Version: header;您绝对不能删除MIME-Version: header; it's what identifies this as a MIME message.这就是将其标识为 MIME 消息的原因。

The From: header should indeed be RFC2047-encoded, and the documentation suggests that it will be "when the message is serialized". From: header 确实应该是 RFC2047 编码的,并且文档表明它将是“当消息被序列化时”。 When you print(msg) you are not properly serializing it;当您print(msg)时,您没有正确序列化它; you want print(msg.as_string()) which does exhibit the required serialization.你想要print(msg.as_string())确实表现出所需的序列化。

When it comes to the transfer encoding, Python's email library has an unattractive penchant for using base64 for content which could very well be encoded as quoted-printable instead.当涉及到传输编码时,Python 的email库对使用base64的内容很有吸引力,而这些内容很可能被编码为可引用打印。 You can't really reliably send the content completely unencoded (though if you wanted to, the MIME 8bit or binary encodings would be able to accommodate that; but for backwards compatibility, SMTP requires everything to be encoded into a 7-bit representation).您不能真正可靠地发送完全未编码的内容(尽管如果您愿意,MIME 8bitbinary编码将能够适应这种情况;但为了向后兼容,SMTP 要求将所有内容编码为 7 位表示)。

In the old email library, various shenanigans were required to do this, but in the new EmailMessage API introduced in Python 3.6, you really only have to add cte='quoted-printable' to the set_content call.在旧的email库中,需要各种恶作剧来执行此操作,但在 Python 3.6 中引入的新EmailMessage API 中,您真的只有添加set_content cte='quoted-printable'

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

Unfortunately, figuring this out from the documentation is next to impossible.不幸的是,从文档中弄清楚这一点几乎是不可能的。 The documentation for set_content basically just defers to the policy which obscurely points to the raw_data_manager (if you even notice the link)... where finally you hopefully notice the presence of the cte keyword argument. set_content的文档基本上只是遵循模糊指向raw_data_managerpolicy (如果您甚至注意到链接)......最后您希望注意到cte关键字参数的存在。

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

(As an aside, you might also want to (顺便说一句,您可能还想

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

in the body text.)在正文中。)

If you go for an 8bit or binary content transfer encoding, the difference between them is that the former has a line length limit (max 900-something characters) whereas the latter is completely unconstrained.如果您使用 go 进行8bitbinary内容传输编码,它们之间的区别在于前者有行长限制(最多 900 个字符),而后者完全不受限制。 But you need to be sure that the entire SMTP transfer path is 8-bit clean (at which point you might as well pivot to Unicode email / ESMTP SMTPUTF8 entirely). But you need to be sure that the entire SMTP transfer path is 8-bit clean (at which point you might as well pivot to Unicode email / ESMTP SMTPUTF8 entirely).

For your possible entertainment, here are some old questions with crazy hacks for Python 3.5 and earlier.为了您的娱乐,这里有一些关于 Python 3.5 及更早版本疯狂黑客的老问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM