You absolutely must not remove the MIME-Version:
header; it's what identifies this as a MIME message.
The From:
header should indeed be RFC2047-encoded, and the documentation suggests that it will be "when the message is serialized". When you print(msg)
you are not properly serializing it; you want print(msg.as_string())
which does exhibit the required serialization.
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. 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).
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.
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.
Demo: https://ideone.com/eLAt11
(As an aside, you might also want to
replace('
', '
')
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. 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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…