Code

Opened 7 years ago

Closed 7 years ago

#4771 closed (wontfix)

EmailHTML - EmailMessage with HTML and related/inline images support

Reported by: sime <simon@…> Owned by: nobody
Component: Core (Mail) Version: master
Severity: Keywords: EmailMessage multipart mail html attachments Content-ID
Cc: nick.lane.au@… Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Seems we need the ability to specify Content-Type 'name' header for attachments, when using the new mail objects. I'm trying to send an HTML mail with images, using EmailMultiAlternatives, attach_alternative, and attach_file, but the resulting message isn't readable. It's attaching everything OK, but not with the right headers.

Attachments (0)

Change History (4)

comment:1 Changed 7 years ago by nick.lane.au@…

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I haven't looked into this yet, but you might need to use the Content-ID header for the image.
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/473810

comment:2 Changed 7 years ago by sime <simon@…>

  • Cc nick.lane.au@… added
  • Summary changed from EmailMultiAlternatives doesn't support named image/media attachments to EmailHTML - EmailMessage with HTML and related/inline images support
  • Triage Stage changed from Unreviewed to Design decision needed

Here is a derivative of EmailMessage that allows nice easy HTML with inline images. It also provides a multipart/related-safe way of attaching HTML and automatically fixes file references in your HTML to point to inline attachments.

class EmailHTML(EmailMessage):
    multipart_subtype = 'related'
    html = None
    related_ids = []
    
    def message(self):
        if self.html:
            for id in self.related_ids:
                self.html = self.html.replace(id, 'cid:' + id)
            encoding = self.encoding or settings.DEFAULT_CHARSET
            ha = SafeMIMEText(self.html, 'html', encoding)
            if self.body:
                a = SafeMIMEMultipart(_subtype='alternative')
                a.attach(SafeMIMEText(smart_str(self.body, encoding), self.content_subtype, encoding))
                a.attach(ha)
            else:
                a = ha
            self.attachments.insert(0, a)
            self.body = None
            self.html = None
        return super(EmailHTML, self).message()
        
    def attach_html(self, html):
        """
        Specify HTML to include in the message.
        """
        self.html = html
                    
    def attach_related(self, path, mimetype=None):
        """
        Attaches a file from the filesystem, with a Content-ID.
        For use with multipart/related messages.
        """
        filename = os.path.basename(path)
        content = open(path, 'rb').read()
        self.attachments.append((filename, content, mimetype, True))
        self.related_ids += [ filename ]

    def _create_attachment(self, filename, content, mimetype=None, with_id=False):
        """
        Convert the filename, content, mimetype triple into a MIME attachment
        object. Adjust headers to use Content-ID where applicable.
        """
        attachment = super(EmailHTML, self)._create_attachment(filename, content, mimetype)
        if filename and with_id:
            # change headers to suit
            del(attachment['Content-Disposition'])
            mimetype = attachment['Content-Type']
            del(attachment['Content-Type'])
            attachment.add_header('Content-Type', mimetype, name=filename)
            attachment.add_header('Content-ID', '<%s>' % filename)
        return attachment

comment:3 Changed 7 years ago by simo <simon@…>

If we're including multipart and attachment support in core.mail, then I think this (or similar) should be included also.

See also ticket #4781 a typo fix required to make this class work.

comment:4 Changed 7 years ago by jacob

  • Resolution set to wontfix
  • Status changed from new to closed

I think this doesn't make much sense as a built-in: HTML email is so weird that pretty much everyone wants to do things differently (my HTMLEmail class is similar to the above, but different in a few ways). Since there really isn't a one-size-fits-all (or even a one-size-fits-most) solution, I'm going to close this wontfix.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.