1
0
mirror of https://github.com/django/django.git synced 2025-08-23 10:19:13 +00:00
django/tests/mail/test_deprecated.py
Mike Edmunds 9ab1991689 Fixed #35581 -- Updated django.core.mail to Python's modern email API.
- Changed EmailMessage.message() to construct a "modern email API"
  email.message.EmailMessage and added policy keyword arg.
- Added support for modern MIMEPart objects in EmailMessage.attach()
  (and EmailMessage constructor, EmailMessage.attachments list).
- Updated SMTP EmailBackend to use modern email.policy.SMTP.

Deprecated:
- Attaching MIMEBase objects (replace with MIMEPart)
- BadHeaderError (modern email uses ValueError)
- SafeMIMEText, SafeMIMEMultipart (unnecessary for modern email)
- django.core.mail.forbid_multi_line_headers()
  (undocumented, but exposed via `__all__` and in wide use)
- django.core.mail.message.sanitize_address()
  (undocumented, but in wide use)

Removed without deprecation (all undocumented):
- EmailMessage.mixed_subtype
- EmailMultiAlternatives.alternative_subtype
- Support for setting (undocumented) EmailMessage.encoding property
  to a legacy email.charset.Charset object

Related changes:
- Dropped tests for incorrect RFC 2047 encoding of non-ASCII email
  address localparts. This is specifically prohibited by RFC 2047, and
  not supported by any known MTA or email client. (Python still
  mis-applies encoded-word to non-ASCII localparts, but it is a bug that
  may be fixed in the future.)
- Added tests that try to discourage using Python's legacy email APIs
  in future updates to django.core.mail.
2025-07-25 13:50:02 +02:00

123 lines
4.5 KiB
Python

# RemovedInDjango70Warning: This entire file.
from email.mime.text import MIMEText
from django.core.mail import (
EmailAlternative,
EmailAttachment,
EmailMessage,
EmailMultiAlternatives,
)
from django.core.mail.message import forbid_multi_line_headers, sanitize_address
from django.test import SimpleTestCase, ignore_warnings
from django.utils.deprecation import RemovedInDjango70Warning
from .tests import MailTestsMixin
class DeprecationWarningTests(MailTestsMixin, SimpleTestCase):
def test_deprecated_on_import(self):
"""
These items are not typically called from user code,
so generate deprecation warnings immediately at the time
they are imported from django.core.mail.
"""
cases = [
# name, msg
(
"BadHeaderError",
"BadHeaderError is deprecated. Replace with ValueError.",
),
(
"SafeMIMEText",
"SafeMIMEText is deprecated. The return value of"
" EmailMessage.message() is an email.message.EmailMessage.",
),
(
"SafeMIMEMultipart",
"SafeMIMEMultipart is deprecated. The return value of"
" EmailMessage.message() is an email.message.EmailMessage.",
),
]
for name, msg in cases:
with self.subTest(name=name):
with self.assertWarnsMessage(RemovedInDjango70Warning, msg):
__import__("django.core.mail", fromlist=[name])
def test_sanitize_address_deprecated(self):
msg = (
"The internal API sanitize_address() is deprecated."
" Python's modern email API (with email.message.EmailMessage or"
" email.policy.default) will handle most required validation and"
" encoding. Use Python's email.headerregistry.Address to construct"
" formatted addresses from component parts."
)
with self.assertWarnsMessage(RemovedInDjango70Warning, msg):
sanitize_address("to@example.com", "ascii")
def test_forbid_multi_line_headers_deprecated(self):
msg = (
"The internal API forbid_multi_line_headers() is deprecated."
" Python's modern email API (with email.message.EmailMessage or"
" email.policy.default) will reject multi-line headers."
)
with self.assertWarnsMessage(RemovedInDjango70Warning, msg):
forbid_multi_line_headers("To", "to@example.com", "ascii")
class UndocumentedFeatureErrorTests(SimpleTestCase):
"""
These undocumented features were removed without going through deprecation.
In case they were being used, they now raise errors.
"""
def test_undocumented_mixed_subtype(self):
"""
Trying to use the previously undocumented, now unsupported
EmailMessage.mixed_subtype causes an error.
"""
msg = (
"EmailMessage no longer supports"
" the undocumented `mixed_subtype` attribute"
)
email = EmailMessage(
attachments=[EmailAttachment(None, b"GIF89a...", "image/gif")]
)
email.mixed_subtype = "related"
with self.assertRaisesMessage(AttributeError, msg):
email.message()
def test_undocumented_alternative_subtype(self):
"""
Trying to use the previously undocumented, now unsupported
EmailMultiAlternatives.alternative_subtype causes an error.
"""
msg = (
"EmailMultiAlternatives no longer supports"
" the undocumented `alternative_subtype` attribute"
)
email = EmailMultiAlternatives(
alternatives=[EmailAlternative("", "text/plain")]
)
email.alternative_subtype = "multilingual"
with self.assertRaisesMessage(AttributeError, msg):
email.message()
@ignore_warnings(category=RemovedInDjango70Warning)
class DeprecatedCompatibilityTests(SimpleTestCase):
def test_bad_header_error(self):
"""
Existing code that catches deprecated BadHeaderError should be
compatible with modern email (which raises ValueError instead).
"""
from django.core.mail import BadHeaderError
with self.assertRaises(BadHeaderError):
EmailMessage(subject="Bad\r\nHeader").message()
def test_attachments_mimebase_in_constructor(self):
txt = MIMEText("content1")
msg = EmailMessage(attachments=[txt])
payload = msg.message().get_payload()
self.assertEqual(payload[0], txt)