#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.