Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dccf01a

Browse filesBrowse files
committed
bpo-39757: Use IDNA to encode domain part in email address
While b64/qp can be used to encode most non-ascii headers, the domain part of an email address must conform IDNA ([rfc5890], [rfc5891]) thus be encoded using the punycode algorithm ([rfc3492]). [SMTPUTF8](rfc6531) is no exception. [rfc5890]: https://tools.ietf.org/html/rfc5890 [rfc5891]: https://tools.ietf.org/html/rfc5891 [rfc3492]: https://tools.ietf.org/html/rfc3492 [rfc6531]: https://tools.ietf.org/html/rfc6531#section-3.2
1 parent be7ead6 commit dccf01a
Copy full SHA for dccf01a

File tree

2 files changed

+35
-1
lines changed
Filter options

2 files changed

+35
-1
lines changed

‎Lib/email/_header_value_parser.py

Copy file name to clipboardExpand all lines: Lib/email/_header_value_parser.py
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,10 @@ class Domain(TokenList):
497497

498498
@property
499499
def domain(self):
500-
return ''.join(super().value.split())
500+
return ''.join(super().value.split()).encode('idna').decode('ascii')
501501

502+
def __str__(self):
503+
return super().__str__().encode('idna').decode('ascii')
502504

503505
class DotAtom(TokenList):
504506
token_type = 'dot-atom'

‎Lib/test/test_email/test_generator.py

Copy file name to clipboardExpand all lines: Lib/test/test_email/test_generator.py
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,38 @@ def test_cte_type_7bit_transforms_8bit_cte(self):
271271
g.flatten(msg)
272272
self.assertEqual(s.getvalue(), expected)
273273

274+
def test_unicode_domain_transforms_idna(self):
275+
msg = EmailMessage()
276+
msg['From'] = "john@examplé.com"
277+
msg['To'] = "Joe <joe@examplé.com>"
278+
279+
expected = textwrap.dedent("""\
280+
From: john@xn--exampl-gva.com
281+
To: Joe <joe@xn--exampl-gva.com>
282+
283+
""").encode('ascii').replace(b'\n', b'\r\n')
284+
285+
s = io.BytesIO()
286+
g = BytesGenerator(s, policy=policy.SMTP)
287+
g.flatten(msg)
288+
self.assertEqual(s.getvalue(), expected)
289+
290+
def test_unicode_domain_transforms_idna_smtputf8_policy(self):
291+
msg = EmailMessage()
292+
msg['From'] = "john@examplé.com"
293+
msg['To'] = "Joe <joe@examplé.com>"
294+
295+
expected = textwrap.dedent("""\
296+
From: john@xn--exampl-gva.com
297+
To: Joe <joe@xn--exampl-gva.com>
298+
299+
""").encode('utf-8').replace(b'\n', b'\r\n')
300+
301+
s = io.BytesIO()
302+
g = BytesGenerator(s, policy=policy.SMTPUTF8)
303+
g.flatten(msg)
304+
self.assertEqual(s.getvalue(), expected)
305+
274306
def test_smtputf8_policy(self):
275307
msg = EmailMessage()
276308
msg['From'] = "Páolo <főo@bar.com>"

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.