https://github.com/python/cpython/commit/03108045d25e4a75575d8a19d3187599e17277a4 commit: 03108045d25e4a75575d8a19d3187599e17277a4 branch: 3.12 author: Miss Islington (bot) <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2024-04-17T07:55:11Z summary:
[3.12] gh-75171: Fix parsing invalid email address headers starting or ending with a dot (GH-15600) (GH-117964) (cherry picked from commit 8cc9adbfddc8e37cf7d621b12754eecb0584f5da) Co-authored-by: tsufeki <[email protected]> Co-authored-by: Tim Bell <[email protected]> Co-authored-by: Serhiy Storchaka <[email protected]> files: A Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst M Lib/email/_header_value_parser.py M Lib/test/test_email/test__header_value_parser.py M Lib/test/test_email/test_headerregistry.py diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index e4a342d446f6a3..0cf23fc9f656b1 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -566,12 +566,14 @@ def display_name(self): if res[0].token_type == 'cfws': res.pop(0) else: - if res[0][0].token_type == 'cfws': + if (isinstance(res[0], TokenList) and + res[0][0].token_type == 'cfws'): res[0] = TokenList(res[0][1:]) if res[-1].token_type == 'cfws': res.pop() else: - if res[-1][-1].token_type == 'cfws': + if (isinstance(res[-1], TokenList) and + res[-1][-1].token_type == 'cfws'): res[-1] = TokenList(res[-1][:-1]) return res.value @@ -586,9 +588,13 @@ def value(self): quote = True if len(self) != 0 and quote: pre = post = '' - if self[0].token_type=='cfws' or self[0][0].token_type=='cfws': + if (self[0].token_type == 'cfws' or + isinstance(self[0], TokenList) and + self[0][0].token_type == 'cfws'): pre = ' ' - if self[-1].token_type=='cfws' or self[-1][-1].token_type=='cfws': + if (self[-1].token_type == 'cfws' or + isinstance(self[-1], TokenList) and + self[-1][-1].token_type == 'cfws'): post = ' ' return pre+quote_string(self.display_name)+post else: @@ -1772,7 +1778,10 @@ def get_name_addr(value): raise errors.HeaderParseError( "expected name-addr but found '{}'".format(token)) if leader is not None: - token[0][:0] = [leader] + if isinstance(token[0], TokenList): + token[0][:0] = [leader] + else: + token[:0] = [leader] leader = None name_addr.append(token) token, value = get_angle_addr(value) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py index f7e80749c456f8..dd1af9954c61da 100644 --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -1805,6 +1805,32 @@ def test_get_name_addr_qs_name(self): self.assertIsNone(name_addr.route) self.assertEqual(name_addr.addr_spec, '[email protected]') + def test_get_name_addr_ending_with_dot_without_space(self): + name_addr = self._test_get_x(parser.get_name_addr, + 'John X.<[email protected]>', + 'John X.<[email protected]>', + '"John X."<[email protected]>', + [errors.ObsoleteHeaderDefect], + '') + self.assertEqual(name_addr.display_name, 'John X.') + self.assertEqual(name_addr.local_part, 'jxd') + self.assertEqual(name_addr.domain, 'example.com') + self.assertIsNone(name_addr.route) + self.assertEqual(name_addr.addr_spec, '[email protected]') + + def test_get_name_addr_starting_with_dot(self): + name_addr = self._test_get_x(parser.get_name_addr, + '. Doe <[email protected]>', + '. Doe <[email protected]>', + '". Doe" <[email protected]>', + [errors.InvalidHeaderDefect, errors.ObsoleteHeaderDefect], + '') + self.assertEqual(name_addr.display_name, '. Doe') + self.assertEqual(name_addr.local_part, 'jxd') + self.assertEqual(name_addr.domain, 'example.com') + self.assertIsNone(name_addr.route) + self.assertEqual(name_addr.addr_spec, '[email protected]') + def test_get_name_addr_with_route(self): name_addr = self._test_get_x(parser.get_name_addr, '"Roy.A.Bear" <@two.example.com: [email protected]>', diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 25347ef13c2147..bb7ca8dfd8c52c 100644 --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1237,6 +1237,26 @@ class TestAddressHeader(TestHeaderBase): 'example.com', None), + 'name_ending_with_dot_without_space': + ('John X.<[email protected]>', + [errors.ObsoleteHeaderDefect], + '"John X." <[email protected]>', + 'John X.', + '[email protected]', + 'jxd', + 'example.com', + None), + + 'name_starting_with_dot': + ('. Doe <[email protected]>', + [errors.InvalidHeaderDefect, errors.ObsoleteHeaderDefect], + '". Doe" <[email protected]>', + '. Doe', + '[email protected]', + 'jxd', + 'example.com', + None), + } # XXX: Need many more examples, and in particular some with names in diff --git a/Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst b/Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst new file mode 100644 index 00000000000000..c776c73ba160e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-08-29-20-26-08.bpo-30988.b-_h5O.rst @@ -0,0 +1 @@ +Fix parsing of emails with invalid address headers having a leading or trailing dot. Patch by tsufeki. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: [email protected]
