Opened 45 minutes ago

Last modified 19 minutes ago

#37429 new Bug

Cannot create multipart alternative mail with subparts

Reported by: jddupas Owned by:
Component: Core (Mail) Version: 6.1
Severity: Normal Keywords: email
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by jddupas)

I want to create a mail with a plain/text alternative, and an html alternative containing images referenced by CID.
It used to be possible before Django 6, but the new API fails when trying to build such mail:

multipart/alternative
├── text/plain; charset=UTF-8
└── multipart/related; type="text/html"
    ├── text/html; charset=UTF-8
    └── image/png
        Content-ID: <image001>
        Content-Disposition: inline

I tried to create the HTML + image part using a MIMEPart(), but there is no way to attach it to the Django EmailMultiAlternatives.

The attach_alternative() method does not support taking a MimePart as content parameter. It requires a content-type.
If the content-type is text, in _add_bodies(), it calls add_alternative() with a charset parameter, and fails as the charset argument is not supported by the content manager when inserting a MimePart.
If the content-type is something else, _add_bodies() converts the whole MimePart into base64 and insert it unstructured.

If I use the attach() method instead, the part is properly inserted, but the whole messages switch to mixed content-type, and not alternative content-type.

Change History (3)

comment:1 by jddupas, 38 minutes ago

Description: modified (diff)

comment:2 by jddupas, 22 minutes ago

Description: modified (diff)

comment:3 by jddupas, 19 minutes ago

One way to fix this, would be to modifiy EmailMultiAlternatives._add_bodies() to support MIMEPart:

                if maintype == "text":
                    if isinstance(content, bytes):
                        content = content.decode()
                    msg.add_alternative(content, subtype=subtype, charset=encoding)
                elif isinstance(content, email.message.MIMEPart):
                    msg.attach(content)
                else:
                    content = force_bytes(content, encoding=encoding, strings_only=True)
                    msg.add_alternative(content, maintype=maintype, subtype=subtype)

As the MIMEPart already define its content type, it should just be attached to the python Message.

Note: See TracTickets for help on using tickets.
Back to Top