The modern email package incorrectly encodes a non-ASCII email address 'local-part' (username) using an RFC 2047 encoded-word, resulting in undeliverable email:
An 'encoded-word' MUST NOT appear in any portion of an 'addr-spec'.
This issue is related to #83938, which covers the same problem in an email address domain. In a comment there, @bitdancer says:
What should be happening here is that an error should be raised when that header is set (or possibly when it is accessed/serialized, but when set would be better I think) saying that there is non-ascii in the domain part.
Since email.policy.SMTPUTF8 allows non-ASCII addr-specs, I think the error will have to be when the header is serialized with a utf8=False policy (and not when the header is set):
# Expected behavior (using `msg` from example above):
>>> msg.as_bytes()
ValueError('Non-ASCII username requires SMTPUTF8 policy')
# This already works correctly:
>>> from email.policy import SMTPUTF8
msg.as_bytes(policy=SMTPUTF8)
b'To: j\xc3\xb6rg@example.com\r\n\r\n'
More info:
The only spec-compliant way to support a non-ASCII localpart seems to be transmitting raw utf-8 using the RFC 6531 SMTPUTF8 extension.
I haven't been able to find any mail software that actually supports an RFC 2047 encoded-word localpart. (Exim has options to support non-ASCII localparts using RFC 5891 A-labels—a.k.a. "punycode"—but that's a different encoding.)
CPython versions tested on:
3.8, 3.9, 3.10, 3.11, 3.12, 3.13, CPython main branch
Bug report
Bug description:
The modern email package incorrectly encodes a non-ASCII email address 'local-part' (username) using an RFC 2047 encoded-word, resulting in undeliverable email:
That use is prohibited by RFC 2047 section 5:
This issue is related to #83938, which covers the same problem in an email address domain. In a comment there, @bitdancer says:
Since email.policy.SMTPUTF8 allows non-ASCII addr-specs, I think the error will have to be when the header is serialized with a utf8=False policy (and not when the header is set):
More info:
CPython versions tested on:
3.8, 3.9, 3.10, 3.11, 3.12, 3.13, CPython main branch
Operating systems tested on:
Linux, macOS