gh-134155: fix AttributeError in email._header_value_parser.get_address (#134194)

Append the defect to defects instead of to the parse tree.

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
Sergey Miryanov 2025-06-05 10:28:11 -07:00 committed by GitHub
parent 1b55e12766
commit d9cad074d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 2 deletions

View file

@ -1575,7 +1575,7 @@ def get_dtext(value):
def _check_for_early_dl_end(value, domain_literal):
if value:
return False
domain_literal.append(errors.InvalidHeaderDefect(
domain_literal.defects.append(errors.InvalidHeaderDefect(
"end of input inside domain-literal"))
domain_literal.append(ValueTerminal(']', 'domain-literal-end'))
return True
@ -1594,9 +1594,9 @@ def get_domain_literal(value):
raise errors.HeaderParseError("expected '[' at start of domain-literal "
"but found '{}'".format(value))
value = value[1:]
domain_literal.append(ValueTerminal('[', 'domain-literal-start'))
if _check_for_early_dl_end(value, domain_literal):
return domain_literal, value
domain_literal.append(ValueTerminal('[', 'domain-literal-start'))
if value[0] in WSP:
token, value = get_fws(value)
domain_literal.append(token)

View file

@ -2491,6 +2491,38 @@ class TestParser(TestParserMixin, TestEmailBase):
self.assertEqual(address.all_mailboxes[0].domain, 'example.com')
self.assertEqual(address.all_mailboxes[0].addr_spec, '"example example"@example.com')
def test_get_address_with_invalid_domain(self):
address = self._test_get_x(parser.get_address,
'<T@[',
'<T@[]>',
'<T@[]>',
[errors.InvalidHeaderDefect, # missing trailing '>' on angle-addr
errors.InvalidHeaderDefect, # end of input inside domain-literal
],
'')
self.assertEqual(address.token_type, 'address')
self.assertEqual(len(address.mailboxes), 0)
self.assertEqual(len(address.all_mailboxes), 1)
self.assertEqual(address.all_mailboxes[0].domain, '[]')
self.assertEqual(address.all_mailboxes[0].local_part, 'T')
self.assertEqual(address.all_mailboxes[0].token_type, 'invalid-mailbox')
self.assertEqual(address[0].token_type, 'invalid-mailbox')
address = self._test_get_x(parser.get_address,
'!an??:=m==fr2@[C',
'!an??:=m==fr2@[C];',
'!an??:=m==fr2@[C];',
[errors.InvalidHeaderDefect, # end of header in group
errors.InvalidHeaderDefect, # end of input inside domain-literal
],
'')
self.assertEqual(address.token_type, 'address')
self.assertEqual(len(address.mailboxes), 0)
self.assertEqual(len(address.all_mailboxes), 1)
self.assertEqual(address.all_mailboxes[0].domain, '[C]')
self.assertEqual(address.all_mailboxes[0].local_part, '=m==fr2')
self.assertEqual(address.all_mailboxes[0].token_type, 'invalid-mailbox')
self.assertEqual(address[0].token_type, 'group')
# get_address_list
@ -2765,6 +2797,19 @@ class TestParser(TestParserMixin, TestEmailBase):
)
self.assertEqual(message_id.token_type, 'message-id')
def test_parse_message_id_with_invalid_domain(self):
message_id = self._test_parse_x(
parser.parse_message_id,
"<T@[",
"<T@[]>",
"<T@[]>",
[errors.ObsoleteHeaderDefect] + [errors.InvalidHeaderDefect] * 2,
[],
)
self.assertEqual(message_id.token_type, 'message-id')
self.assertEqual(str(message_id.all_defects[-1]),
"end of input inside domain-literal")
def test_parse_message_id_with_remaining(self):
message_id = self._test_parse_x(
parser.parse_message_id,

View file

@ -0,0 +1 @@
:mod:`email`: Fix parsing of email message ID with invalid domain.