Skip to content

Commit 25cf1cb

Browse files
medmundsjacobtylerwalls
authored andcommitted
Refs #36664 -- Updated SMTP EmailBackend tests for Python 3.15.
Versions of Python prior to 3.15 would incorrectly encode non-ASCII email addresses using rfc2047, resulting in undeliverable email. The SMTP EmailBackend detects and prevents that (#35713). Python 3.15 fixes that behavior (CPython issue gh-122476). Updated test_rejects_non_ascii_local_part() to feature-detect the fix (in case it is backported) and check for a representative section of the Python error message if so; otherwise test for the SMTP EmailBackend workaround. Updated comments to clarify need and requirement.
1 parent ed54863 commit 25cf1cb

2 files changed

Lines changed: 24 additions & 11 deletions

File tree

django/core/mail/backends/smtp.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,10 @@ def prep_address(self, address, force_ascii=True):
217217
# Django allows local mailboxes like "From: webmaster" (#15042).
218218
defects.discard("addr-spec local part with no domain")
219219
if not force_ascii:
220-
# Non-ASCII local-part is valid with SMTPUTF8. Remove once
221-
# https://github.com/python/cpython/issues/81074 is fixed.
220+
# PY315: Non-ASCII local-part is valid with SMTPUTF8. This check
221+
# can be removed once the minimum supported Python version is 3.15
222+
# (so the fix for https://github.com/python/cpython/issues/81074
223+
# is in all supported versions).
222224
defects.discard("local-part contains non-ASCII characters)")
223225
if defects:
224226
raise ValueError(f"Invalid address {address!r}: {'; '.join(defects)}")

tests/mail/test_backends.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import ssl
66
import sys
77
import tempfile
8+
from email.errors import HeaderWriteError
9+
from email.message import EmailMessage as PyEmailMessage
810
from io import StringIO
911
from pathlib import Path
1012
from smtplib import SMTPException
@@ -1093,17 +1095,26 @@ def test_does_not_reencode_idna(self):
10931095
)
10941096

10951097
def test_rejects_non_ascii_local_part(self):
1096-
"""
1097-
The SMTP EmailBackend does not currently support non-ASCII local-parts.
1098-
(That would require using the RFC 6532 SMTPUTF8 extension.) #35713.
1099-
"""
1098+
# The SMTP EmailBackend must work around invalid email encoding caused
1099+
# by https://github.com/python/cpython/issues/122476 (#35713).
1100+
try:
1101+
# Detect fix for CPython issue gh-122476.
1102+
message = PyEmailMessage()
1103+
message["To"] = "nø@example.dk"
1104+
message.as_bytes()
1105+
except HeaderWriteError:
1106+
# PY315: Error from Python email generator.
1107+
msg = "Non-ASCII local-part 'nø' is invalid"
1108+
else:
1109+
# Python <=3.14: Error from smtp.EmailBackend.prep_address().
1110+
msg = (
1111+
"Invalid address 'nø@example.dk': local-part contains "
1112+
"non-ASCII characters"
1113+
)
1114+
11001115
backend = self.create_backend()
1101-
backend.connection = mock.Mock(spec=object())
11021116
email = EmailMessage(to=["nø@example.dk"])
1103-
with self.assertRaisesMessage(
1104-
ValueError,
1105-
"Invalid address 'nø@example.dk': local-part contains non-ASCII characters",
1106-
):
1117+
with self.assertRaisesMessage((ValueError, HeaderWriteError), msg):
11071118
backend.send_messages([email])
11081119

11091120
def test_prep_address_without_force_ascii(self):

0 commit comments

Comments
 (0)