summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Edmunds <medmunds@gmail.com>2026-05-13 12:25:44 -0700
committerJacob Walls <jacobtylerwalls@gmail.com>2026-05-14 07:49:25 -0400
commit25cf1cbb1cb92c6c57b76cc43d697cfdc61f568f (patch)
tree18af75c4dfb75d6c65142dc4c6211944b0e5471a
parented5486376989c08b34cc62e7c8ba4a07bd60047d (diff)
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.
-rw-r--r--django/core/mail/backends/smtp.py6
-rw-r--r--tests/mail/test_backends.py29
2 files changed, 24 insertions, 11 deletions
diff --git a/django/core/mail/backends/smtp.py b/django/core/mail/backends/smtp.py
index e7cca2c01d..84154dd1c0 100644
--- a/django/core/mail/backends/smtp.py
+++ b/django/core/mail/backends/smtp.py
@@ -217,8 +217,10 @@ class EmailBackend(BaseEmailBackend):
# Django allows local mailboxes like "From: webmaster" (#15042).
defects.discard("addr-spec local part with no domain")
if not force_ascii:
- # Non-ASCII local-part is valid with SMTPUTF8. Remove once
- # https://github.com/python/cpython/issues/81074 is fixed.
+ # PY315: Non-ASCII local-part is valid with SMTPUTF8. This check
+ # can be removed once the minimum supported Python version is 3.15
+ # (so the fix for https://github.com/python/cpython/issues/81074
+ # is in all supported versions).
defects.discard("local-part contains non-ASCII characters)")
if defects:
raise ValueError(f"Invalid address {address!r}: {'; '.join(defects)}")
diff --git a/tests/mail/test_backends.py b/tests/mail/test_backends.py
index eec7568a2d..0782b18afe 100644
--- a/tests/mail/test_backends.py
+++ b/tests/mail/test_backends.py
@@ -5,6 +5,8 @@ import socket
import ssl
import sys
import tempfile
+from email.errors import HeaderWriteError
+from email.message import EmailMessage as PyEmailMessage
from io import StringIO
from pathlib import Path
from smtplib import SMTPException
@@ -1093,17 +1095,26 @@ class SMTPBackendTests(SharedEmailBackendTests, SMTPBackendTestsBase):
)
def test_rejects_non_ascii_local_part(self):
- """
- The SMTP EmailBackend does not currently support non-ASCII local-parts.
- (That would require using the RFC 6532 SMTPUTF8 extension.) #35713.
- """
+ # The SMTP EmailBackend must work around invalid email encoding caused
+ # by https://github.com/python/cpython/issues/122476 (#35713).
+ try:
+ # Detect fix for CPython issue gh-122476.
+ message = PyEmailMessage()
+ message["To"] = "nø@example.dk"
+ message.as_bytes()
+ except HeaderWriteError:
+ # PY315: Error from Python email generator.
+ msg = "Non-ASCII local-part 'nø' is invalid"
+ else:
+ # Python <=3.14: Error from smtp.EmailBackend.prep_address().
+ msg = (
+ "Invalid address 'nø@example.dk': local-part contains "
+ "non-ASCII characters"
+ )
+
backend = self.create_backend()
- backend.connection = mock.Mock(spec=object())
email = EmailMessage(to=["nø@example.dk"])
- with self.assertRaisesMessage(
- ValueError,
- "Invalid address 'nø@example.dk': local-part contains non-ASCII characters",
- ):
+ with self.assertRaisesMessage((ValueError, HeaderWriteError), msg):
backend.send_messages([email])
def test_prep_address_without_force_ascii(self):