#36746: IndexError in prep_address() when parsing invalid email addresses like
'to@'
-------------------------------+---------------------------------------
     Reporter:  Mahdi Dehghan  |                     Type:  Bug
       Status:  new            |                Component:  Core (Mail)
      Version:  dev            |                 Severity:  Normal
     Keywords:                 |             Triage Stage:  Unreviewed
    Has patch:  1              |      Needs documentation:  0
  Needs tests:  0              |  Patch needs improvement:  0
Easy pickings:  0              |                    UI/UX:  0
-------------------------------+---------------------------------------
 When parsing invalid email addresses (such as 'to@') in the SMTP backend's
 prep_address() method, Python's email parser raises an IndexError instead
 of the expected ValueError. This causes the test
 test_avoids_sending_to_invalid_addresses to fail.

 **Steps to reproduce:
 1. Run Django's test suite: `./runtests.py
 mail.tests.SMTPBackendTests.test_avoids_sending_to_invalid_addresses`
 2. The test fails with IndexError when trying to parse 'to@'

 **Root cause:
 The prep_address() method at line 172 in
 `django/core/mail/backends/smtp.py` directly calls
 `AddressHeader.value_parser(address)` without exception handling. When
 parsing malformed addresses like 'to@', Python's email parser first raises
 HeaderParseError, then during exception handling attempts to parse the
 address differently, which leads to an IndexError when trying to access
 `value[0]` on an empty string.

 **Proposed solution:
 Wrap the `AddressHeader.value_parser()` call in a try-except block to
 catch `HeaderParseError`, `IndexError`, and `ValueError` exceptions,
 converting them to `ValueError` with an appropriate message. This matches
 the pattern already used in the deprecated `sanitize_address()` function
 in `django/core/mail/message.py` (line 115).

 **Expected behavior:
 The prep_address() method should catch parsing exceptions and raise
 ValueError with message "Invalid address" for invalid addresses, matching
 the test's expectation.

 **Actual behavior:
 IndexError: string index out of range is raised from Python's
 email._header_value_parser when parsing addresses like 'to@'.

 **Error traceback:
 ERROR: test_avoids_sending_to_invalid_addresses
 (mail.tests.SMTPBackendTests.test_avoids_sending_to_invalid_addresses)
 [<object object at 0x12d0aff70>] (email_address='to@')
 Verify invalid addresses can't sneak into SMTP commands through
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1965, in get_address
     token, value = get_group(value)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1923, in get_group
     raise errors.HeaderParseError("expected ':' at end of group "
     ^^^^^^^^^^^^^^^^^
 email.errors.HeaderParseError: expected ':' at end of group display name
 but found '@'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1791, in get_mailbox
     token, value = get_name_addr(value)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1777, in get_name_addr
     token, value = get_angle_addr(value)
       ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1702, in get_angle_addr
     raise errors.HeaderParseError(
     ^^^^^^^^^^^^^^^^^
 email.errors.HeaderParseError: expected angle-addr but found '@'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/case.py",
 line 58, in testPartExecutor
     yield
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/unittest/case.py",
 line 539, in subTest
     yield
   File "tests/mail/tests.py", line 3070, in
 test_avoids_sending_to_invalid_addresses
     backend.send_messages([email])
     ^^^^^^^^^^^^^^^^^
   File "django/core/mail/backends/smtp.py", line 138, in send_messages
     sent = self._send(message)
     ^^^^^^^^^^^^^^^^^
   File "django/core/mail/backends/smtp.py", line 151, in _send
     recipients = [self.prep_address(addr) for addr in
 email_message.recipients()]
     ^^^^^^^^^^^^^^^^^
   File "django/core/mail/backends/smtp.py", line 172, in prep_address
     parsed = AddressHeader.value_parser(address)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/headerregistry.py",
 line 333, in value_parser
     address_list, value = parser.get_address_list(value)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1988, in get_address_list
     token, value = get_address(value)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1968, in get_address
     token, value = get_mailbox(value)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1794, in get_mailbox
     token, value = get_addr_spec(value)
     ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1647, in get_addr_spec
     token, value = get_domain(value[1:])
       ^^^^^^^^^^^^^^^^^
   File
 
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/email/_header_value_parser.py",
 line 1604, in get_domain
     if value[0] in CFWS_LEADER:
       ^^^^^^^^^^^^^^^^^
 IndexError: string index out of range
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36746>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019a9ee65096-08588ef5-281b-4613-8a80-66827969c0df-000000%40eu-central-1.amazonses.com.

Reply via email to