]> granicus.if.org Git - python/commitdiff
bpo-37482: Fix email address name with encoded words and special chars (GH-14561)
authorbsiem <52461103+bsiem@users.noreply.github.com>
Wed, 21 Aug 2019 23:00:39 +0000 (01:00 +0200)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 21 Aug 2019 23:00:39 +0000 (16:00 -0700)
Special characters in email address header display names are normally
put within double quotes. However, encoded words (=?charset?x?...?=) are
not allowed withing double quotes. When the header contains a word with
special characters and another word that must be encoded, the first one
must also be encoded.

In the next example, the display name in the From header is quoted and
therefore the comma is allowed; in the To header, the comma is not
within quotes and not encoded, which is not allowed and therefore
rejected by some mail servers.

From: "Foo Bar, France" <foo@example.com>
To: Foo Bar, =?utf-8?q?Espa=C3=B1a?= <foo@example.com>

https://bugs.python.org/issue37482

Lib/email/_header_value_parser.py
Lib/test/test_email/test_headerregistry.py
Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst [new file with mode: 0644]

index ea33bd8eda7d39ddce1079ebdbd32d0a8bcb746f..b5003943ab0d97dee00f4162ad9a66cb2174baa6 100644 (file)
@@ -2743,6 +2743,9 @@ def _refold_parse_tree(parse_tree, *, policy):
             wrap_as_ew_blocked -= 1
             continue
         tstr = str(part)
+        if part.token_type == 'ptext' and set(tstr) & SPECIALS:
+            # Encode if tstr contains special characters.
+            want_encoding = True
         try:
             tstr.encode(encoding)
             charset = encoding
index 4758f4b1c52e17e213e2c5b6f30d72032196777a..38f7ddbf06d5cde84b6ce076ae1361fa1f15f527 100644 (file)
@@ -1547,6 +1547,30 @@ class TestAddressAndGroup(TestEmailBase):
 
 class TestFolding(TestHeaderBase):
 
+    def test_address_display_names(self):
+        """Test the folding and encoding of address headers."""
+        for name, result in (
+                ('Foo Bar, France', '"Foo Bar, France"'),
+                ('Foo Bar (France)', '"Foo Bar (France)"'),
+                ('Foo Bar, España', 'Foo =?utf-8?q?Bar=2C_Espa=C3=B1a?='),
+                ('Foo Bar (España)', 'Foo Bar =?utf-8?b?KEVzcGHDsWEp?='),
+                ('Foo, Bar España', '=?utf-8?q?Foo=2C_Bar_Espa=C3=B1a?='),
+                ('Foo, Bar [España]', '=?utf-8?q?Foo=2C_Bar_=5BEspa=C3=B1a=5D?='),
+                ('Foo Bär, France', 'Foo =?utf-8?q?B=C3=A4r=2C?= France'),
+                ('Foo Bär <France>', 'Foo =?utf-8?q?B=C3=A4r_=3CFrance=3E?='),
+                (
+                    'Lôrem ipsum dôlôr sit amet, cônsectetuer adipiscing. '
+                    'Suspendisse pôtenti. Aliquam nibh. Suspendisse pôtenti.',
+                    '=?utf-8?q?L=C3=B4rem_ipsum_d=C3=B4l=C3=B4r_sit_amet=2C_c'
+                    '=C3=B4nsectetuer?=\n =?utf-8?q?adipiscing=2E_Suspendisse'
+                    '_p=C3=B4tenti=2E_Aliquam_nibh=2E?=\n Suspendisse =?utf-8'
+                    '?q?p=C3=B4tenti=2E?=',
+                    ),
+                ):
+            h = self.make_header('To', Address(name, addr_spec='a@b.com'))
+            self.assertEqual(h.fold(policy=policy.default),
+                                    'To: %s <a@b.com>\n' % result)
+
     def test_short_unstructured(self):
         h = self.make_header('subject', 'this is a test')
         self.assertEqual(h.fold(policy=policy.default),
diff --git a/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst b/Misc/NEWS.d/next/Library/2019-07-09-11-20-21.bpo-37482.auzvev.rst
new file mode 100644 (file)
index 0000000..e09ff63
--- /dev/null
@@ -0,0 +1 @@
+Fix serialization of display name in originator or destination address fields with both encoded words and special chars.