diff options
| author | Mike Edmunds <medmunds@gmail.com> | 2026-05-13 12:25:44 -0700 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2026-05-14 07:49:25 -0400 |
| commit | 25cf1cbb1cb92c6c57b76cc43d697cfdc61f568f (patch) | |
| tree | 18af75c4dfb75d6c65142dc4c6211944b0e5471a | |
| parent | ed5486376989c08b34cc62e7c8ba4a07bd60047d (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.py | 6 | ||||
| -rw-r--r-- | tests/mail/test_backends.py | 29 |
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): |
