﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36746	IndexError in prep_address() when parsing invalid email addresses like 'to@'	Mahdi Dehghan	Mahdi Dehghan	"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
}}}"	Bug	closed	Core (Mail)	dev	Normal	needsinfo		Mahdi Dehghan	Unreviewed	1	0	0	0	0	0
