Opened 3 hours ago

Last modified 3 hours ago

#36746 assigned Bug

IndexError in prep_address() when parsing invalid email addresses like 'to@'

Reported by: Mahdi Dehghan Owned by: Mahdi Dehghan
Component: Core (Mail) Version: dev
Severity: Normal Keywords:
Cc: Mahdi Dehghan Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

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

Change History (3)

comment:1 by Mahdi Dehghan, 3 hours ago

I'd like to work on this issue. I have a fix ready.

comment:2 by Mahdi Dehghan, 3 hours ago

Owner: set to Mahdi Dehghan
Status: newassigned

comment:3 by Mahdi Dehghan, 3 hours ago

Version 0, edited 3 hours ago by Mahdi Dehghan (next)
Note: See TracTickets for help on using tickets.
Back to Top