#36478: EmailMessage handles utf-8 encoded text attachments differently in
constructor vs property
------------------------------+----------------------------------------
Reporter: Mike Edmunds | Owner: Mike Edmunds
Type: Bug | Status: assigned
Component: Core (Mail) | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+----------------------------------------
Description changed by Mike Edmunds:
Old description:
> Encoded text attachments set directly in the EmailMessage.attachments
> property are not processed the same as the same content passed to in
> EmailMessage(attachments=...) or EmailMessage.attach(...).
>
> #27007 added special EmailMessage.attach() handling for text content
> encoded as utf-8 bytes. That code is also used for the attachments
> constructor argument, but not for attachments set directly:
>
> {{{#!python
> # Existing test: passes
> 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")
>
> # New test: passes
> def test_attach_text_as_bytes_using_constructor(self):
> msg = EmailMessage(
> attachments=[EmailAttachment("file.txt", b"file content\n",
> "text/plain")]
> )
> 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")
>
> # New test: AttributeError: 'bytes' object has no attribute 'encode'
> def test_attach_text_as_bytes_using_property(self):
> msg = EmailMessage()
> msg.attachments = [EmailAttachment("file.txt", b"file content\n",
> "text/plain")]
> 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")
> }}}
>
> The second added test fails with `AttributeError: 'bytes' object has no
> attribute 'encode` deep in SafeMIMEText.
>
> The EmailMessage documentation implies that
> [https://docs.djangoproject.com/en/5.2/topics/email/#emailmessage-
> objects:~:text=The%20EmailMessage%20class%20is%20initialized%20with%20the%20following%20parameters%20(in%20the%20given%20order%2C%20if%20positional%20arguments%20are%20used).%20All%20parameters%20are%20optional%20and%20can%20be%20set%20at%20any%20time%20prior%20to%20calling%20the%20send()%20method.
> the second and third tests should be equivalent].
>
> (#27007 also added a fallback to application/octet-stream for non-utf-8
> text content, but didn't include a test case for that behavior.)
>
> See also
> https://github.com/django/django/pull/18966#discussion_r2154081996
New description:
Encoded text attachments set directly in the EmailMessage.attachments
property are not processed like the same content passed to
EmailMessage(attachments=...) or EmailMessage.attach(...).
#27007 added EmailMessage.attach() handling for text content encoded as
utf-8 bytes. That code is also used for the attachments constructor
argument, but not for attachments set directly on the object property:
{{{#!python
# Existing test: passes
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")
# New test: passes
def test_attach_text_as_bytes_using_constructor(self):
msg = EmailMessage(
attachments=[EmailAttachment("file.txt", b"file content\n",
"text/plain")]
)
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")
# New test: AttributeError: 'bytes' object has no attribute 'encode'
def test_attach_text_as_bytes_using_property(self):
msg = EmailMessage()
msg.attachments = [EmailAttachment("file.txt", b"file content\n",
"text/plain")]
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")
}}}
The second added test fails with `AttributeError: 'bytes' object has no
attribute 'encode` deep in SafeMIMEText.
The EmailMessage documentation implies that
[https://docs.djangoproject.com/en/5.2/topics/email/#emailmessage-
objects:~:text=The%20EmailMessage%20class%20is%20initialized%20with%20the%20following%20parameters%20(in%20the%20given%20order%2C%20if%20positional%20arguments%20are%20used).%20All%20parameters%20are%20optional%20and%20can%20be%20set%20at%20any%20time%20prior%20to%20calling%20the%20send()%20method.
the second and third tests should be equivalent].
(#27007 also added a fallback to application/octet-stream for non-utf-8
text content, but didn't include a test case for that behavior.)
See also
https://github.com/django/django/pull/18966#discussion_r2154081996
--
--
Ticket URL: <https://code.djangoproject.com/ticket/36478#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/01070197a532e018-542898ff-b98e-4cd0-9793-3f02a66ca6ac-000000%40eu-central-1.amazonses.com.