[Django] #27007: Allow bytes objects as text/* attachments

8 views
Skip to first unread message

Django

unread,
Aug 3, 2016, 11:38:32 AM8/3/16
to django-...@googlegroups.com
#27007: Allow bytes objects as text/* attachments
--------------------------------------+--------------------
Reporter: Feuermurmel | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Core (Mail) | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+--------------------
I've noticed that that `attach()` from `django.core.mail.EmailMessage`
allows a `bytes` object to be passed as content even when the MIME type is
set to `text/plain`. `SafeMIMEText` will then try to decode the text in
the bytes object as UTF-8, which is necessary because the MIME
specifications require `text/*` parts to be decodable with the encoding
specified in the //Content-Type// header. But decoding the `bytes` object
will fail if the bytes object does not contain valid UTF-8 encoded text.

OTOH, `attach_file()` will in that case first try to decode the file's
content but fall back on treating the attachment as binary, setting the
Content-Type to `application/octet-stream`.

I think the fallback provided by `attach_file()` is useful and I would
like to extend `attach()` to that same behavior.

--
Ticket URL: <https://code.djangoproject.com/ticket/27007>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 3, 2016, 11:40:24 AM8/3/16
to django-...@googlegroups.com
#27007: Allow bytes objects as text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: new
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Feuermurmel):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Comment:

I will shortly create a pull request with my proposed changes.

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:1>

Django

unread,
Aug 3, 2016, 11:42:37 AM8/3/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: new
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:2>

Django

unread,
Aug 3, 2016, 11:43:30 AM8/3/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: new
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by timgraham):

Might be a duplicate of #26802 which was committed just a couple weeks
ago.

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:3>

Django

unread,
Aug 3, 2016, 11:59:41 AM8/3/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: new
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Feuermurmel):

Pull request: https://github.com/django/django/pull/7014

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:4>

Django

unread,
Aug 3, 2016, 12:00:02 PM8/3/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: new
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Feuermurmel):

Replying to [comment:3 timgraham]:

Sorry for not mentioning #26802. That change did improve the situation,
allowing `bytes` objects. But it tries to unconditionally decode it as
UTF-8 (compared to the logic in `attach_file()`, which falls back to
treating it as a binary file). This means that if a `bytes` object is
passed which does not contain valid UTF-8, a `UnicodeDecodeError` will be
thrown.

With the changes in the pull request, the behavior is the same as when
attaching a non-UTF-8 file.

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:5>

Django

unread,
Aug 4, 2016, 5:21:27 AM8/4/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
--------------------------------------+------------------------------------

Reporter: Feuermurmel | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1

Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Changes (by claudep):

* needs_better_patch: 0 => 1
* has_patch: 0 => 1
* stage: Unreviewed => Accepted


--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:6>

Django

unread,
Aug 7, 2016, 1:20:26 PM8/7/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
--------------------------------------+------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------

Comment (by Claude Paroz <claude@…>):

In [changeset:"6fe391d437cdf9866c34e30b2f3831e9d12e637b" 6fe391d4]:
{{{
#!CommitTicketReference repository=""
revision="6fe391d437cdf9866c34e30b2f3831e9d12e637b"
Refs #27007 -- Enhanced mail text attachment test

The test now also checks whether the sent message's attachment has the
expected
name, content and mime type.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:7>

Django

unread,
Aug 9, 2016, 2:16:58 PM8/9/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: new
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin

Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* needs_better_patch: 1 => 0
* stage: Accepted => Ready for checkin


Comment:

Pending some small documentation edits.

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:8>

Django

unread,
Aug 12, 2016, 4:39:16 PM8/12/16
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Feuermurmel | Owner: nobody
Type: | Status: closed
Cleanup/optimization |

Component: Core (Mail) | Version: master
Severity: Normal | Resolution: fixed

Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: new => closed
* resolution: => fixed


Comment:

In [changeset:"72d541b61cd7b0a14f70242e2207fdb3f600c4d5" 72d541b]:
{{{
#!CommitTicketReference repository=""
revision="72d541b61cd7b0a14f70242e2207fdb3f600c4d5"
Fixed #27007 -- Handled non-UTF-8 bytes objects for text/* attachments.

The fallback logic which allows non-UTF-8 encoded files to be passed to
attach_file() even when a `text/*` mime type has been specified is
moved to attach(). Both functions now fall back to a content type of
`application/octet-stream`.

A side effect is that a file's content is decoded in memory instead of
opening it in text mode and reading it into a string.

Some mimetype-related logic in _create_attachment() has become
obsolete as the code moved from attach_file() to attach() already
handles this.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:9>

Django

unread,
Jun 26, 2025, 2:54:11 AMJun 26
to django-...@googlegroups.com
#27007: Handle non-UTF-8 bytes objects for text/* attachments
-------------------------------------+-------------------------------------
Reporter: Michael Schwarz | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Sarah Boyce <42296566+sarahboyce@…>):

In [changeset:"23529b662793cdf4725d5f8ff58f0df94b343365" 23529b66]:
{{{#!CommitTicketReference repository=""
revision="23529b662793cdf4725d5f8ff58f0df94b343365"
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.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27007#comment:10>
Reply all
Reply to author
Forward
0 new messages