diff options
author | tsufeki <tsufeki@ymail.com> | 2024-04-17 07:39:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-17 07:39:15 (GMT) |
commit | 8cc9adbfddc8e37cf7d621b12754eecb0584f5da (patch) | |
tree | 9fa5147ca1dbf9e61221f64d0d39efc2bdc94690 /Lib | |
parent | 8123c34faa5aab20edc268c7f8a81e6a765af366 (diff) | |
download | cpython-8cc9adbfddc8e37cf7d621b12754eecb0584f5da.zip cpython-8cc9adbfddc8e37cf7d621b12754eecb0584f5da.tar.gz cpython-8cc9adbfddc8e37cf7d621b12754eecb0584f5da.tar.bz2 |
gh-75171: Fix parsing invalid email address headers starting or ending with a dot (GH-15600)
Co-authored-by: Tim Bell <timothybell@gmail.com>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/email/_header_value_parser.py | 19 | ||||
-rw-r--r-- | Lib/test/test_email/test__header_value_parser.py | 26 | ||||
-rw-r--r-- | Lib/test/test_email/test_headerregistry.py | 20 |
3 files changed, 60 insertions, 5 deletions
diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index e4a342d..0cf23fc 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -566,12 +566,14 @@ class DisplayName(Phrase): 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 @@ class DisplayName(Phrase): 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 f7e8074..dd1af99 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 @@ class TestParser(TestParserMixin, TestEmailBase): self.assertIsNone(name_addr.route) self.assertEqual(name_addr.addr_spec, 'dinsdale@example.com') + def test_get_name_addr_ending_with_dot_without_space(self): + name_addr = self._test_get_x(parser.get_name_addr, + 'John X.<jxd@example.com>', + 'John X.<jxd@example.com>', + '"John X."<jxd@example.com>', + [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, 'jxd@example.com') + + def test_get_name_addr_starting_with_dot(self): + name_addr = self._test_get_x(parser.get_name_addr, + '. Doe <jxd@example.com>', + '. Doe <jxd@example.com>', + '". Doe" <jxd@example.com>', + [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, 'jxd@example.com') + def test_get_name_addr_with_route(self): name_addr = self._test_get_x(parser.get_name_addr, '"Roy.A.Bear" <@two.example.com: dinsdale@example.com>', diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py index 25347ef..bb7ca8d 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.<jxd@example.com>', + [errors.ObsoleteHeaderDefect], + '"John X." <jxd@example.com>', + 'John X.', + 'jxd@example.com', + 'jxd', + 'example.com', + None), + + 'name_starting_with_dot': + ('. Doe <jxd@example.com>', + [errors.InvalidHeaderDefect, errors.ObsoleteHeaderDefect], + '". Doe" <jxd@example.com>', + '. Doe', + 'jxd@example.com', + 'jxd', + 'example.com', + None), + } # XXX: Need many more examples, and in particular some with names in |