mirror of
https://github.com/django/django.git
synced 2025-06-30 07:49:19 +00:00
Fixed #36478 -- Fixed inconsistent mail attachment handling.
Fixed an inconsistency between EmailMessage.attach() and .attachments when attaching bytes content with a text/* mimetype. The attach() function decodes UTF-8 bytes if possible and otherwise changes the mimetype to application/octet-stream to preserve the content's unknown encoding (refs #27007). Providing equivalent content directly in EmailMessage.attachments did not apply the same logic, leading to an "AttributeError: 'bytes' object has no attribute 'encode'" in SafeMIMEText.set_payload(). Updated EmailMessage._create_mime_attachment() to match attach()'s handling for text/* mimetypes with bytes content. Updated test cases to accurately cover behavior on both paths.
This commit is contained in:
parent
68a45d9a80
commit
23529b6627
@ -387,6 +387,15 @@ class EmailMessage:
|
||||
email.Message or EmailMessage object, as well as a str.
|
||||
"""
|
||||
basetype, subtype = mimetype.split("/", 1)
|
||||
if basetype == "text" and isinstance(content, bytes):
|
||||
# This duplicates logic from EmailMessage.attach() to properly
|
||||
# handle EmailMessage.attachments not created through attach().
|
||||
try:
|
||||
content = content.decode()
|
||||
except UnicodeDecodeError:
|
||||
mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
|
||||
basetype, subtype = mimetype.split("/", 1)
|
||||
|
||||
if basetype == "text":
|
||||
encoding = self.encoding or settings.DEFAULT_CHARSET
|
||||
attachment = SafeMIMEText(content, subtype, encoding)
|
||||
|
@ -901,12 +901,39 @@ class MailTests(MailTestsMixin, SimpleTestCase):
|
||||
self.assertEqual(actual.mimetype, expected_mimetype)
|
||||
|
||||
def test_attach_text_as_bytes(self):
|
||||
msg = EmailMessage()
|
||||
msg.attach("file.txt", b"file content\n")
|
||||
filename, content, mimetype = self.get_decoded_attachments(msg)[0]
|
||||
self.assertEqual(filename, "file.txt")
|
||||
self.assertEqual(content, "file content\n")
|
||||
self.assertEqual(mimetype, "text/plain")
|
||||
"""
|
||||
For text/* attachments, EmailMessage.attach() decodes bytes as UTF-8
|
||||
if possible and changes to DEFAULT_ATTACHMENT_MIME_TYPE if not.
|
||||
"""
|
||||
email = EmailMessage()
|
||||
# Mimetype guessing identifies these as text/plain from the .txt extensions.
|
||||
email.attach("utf8.txt", "ütƒ-8\n".encode())
|
||||
email.attach("not-utf8.txt", b"\x86unknown-encoding\n")
|
||||
attachments = self.get_decoded_attachments(email)
|
||||
self.assertEqual(attachments[0], ("utf8.txt", "ütƒ-8\n", "text/plain"))
|
||||
self.assertEqual(
|
||||
attachments[1],
|
||||
("not-utf8.txt", b"\x86unknown-encoding\n", "application/octet-stream"),
|
||||
)
|
||||
|
||||
def test_attach_text_as_bytes_using_property(self):
|
||||
"""
|
||||
The logic described in test_attach_text_as_bytes() also applies
|
||||
when directly setting the EmailMessage.attachments property.
|
||||
"""
|
||||
email = EmailMessage()
|
||||
email.attachments = [
|
||||
("utf8.txt", "ütƒ-8\n".encode(), "text/plain"),
|
||||
("not-utf8.txt", b"\x86unknown-encoding\n", "text/plain"),
|
||||
]
|
||||
attachments = self.get_decoded_attachments(email)
|
||||
self.assertEqual(len(attachments), 2)
|
||||
attachments = self.get_decoded_attachments(email)
|
||||
self.assertEqual(attachments[0], ("utf8.txt", "ütƒ-8\n", "text/plain"))
|
||||
self.assertEqual(
|
||||
attachments[1],
|
||||
("not-utf8.txt", b"\x86unknown-encoding\n", "application/octet-stream"),
|
||||
)
|
||||
|
||||
def test_attach_utf8_text_as_bytes(self):
|
||||
"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user