import os.path import re import mimetypes from email.mime.base import MIMEBase from django.core.mail import EmailMultiAlternatives, SafeMIMEMultipart from django.conf import settings # Source: https://djangosnippets.org/snippets/2215/ class EmailMultiRelated(EmailMultiAlternatives): """A version of EmailMessage that makes it easy to send multipart/related messages. For example, including text and HTML versions with inline images. Returns: EmailMultiAlternatives: EmailMultiAlternatives class """ related_subtype = 'related' def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, connection=None, attachments=None, headers=None, alternatives=None): """Create a new email object that can holds text and HTML content. Args: subject (str, optional): The subject of the email. Defaults to ''. body (str, optional): The body of the email. Defaults to ''. from_email (str, optional): [description]. Defaults to None. to ([type], optional): [description]. Defaults to None. bcc ([type], optional): [description]. Defaults to None. connection ([type], optional): [description]. Defaults to None. attachments ([type], optional): [description]. Defaults to None. headers ([type], optional): [description]. Defaults to None. alternatives ([type], optional): [description]. Defaults to None. """ self.related_attachments = [] super(EmailMultiRelated, self).__init__(subject, body, from_email, to, bcc, connection, attachments, headers, alternatives) def attach_related(self, filename=None, content=None, mimetype=None): """ Attaches a file with the given filename and content. The filename can be omitted and the mimetype is guessed, if not provided. If the first parameter is a MIMEBase subclass it is inserted directly into the resulting message attachments. Args: filename ([type], optional): [description]. Defaults to None. content ([type], optional): [description]. Defaults to None. mimetype ([type], optional): [description]. Defaults to None. """ if isinstance(filename, MIMEBase): assert content == mimetype == None self.related_attachments.append(filename) else: assert content is not None self.related_attachments.append((filename, content, mimetype)) def attach_related_file(self, path, mimetype=None): """Attaches a file from the filesystem.""" filename = os.path.basename(path) content = open(path, 'rb').read() if mimetype is None: mimetypes.init() mimetype = mimetypes.guess_type(filename)[0] self.attach_related(filename, content, mimetype) def _create_message(self, msg): return self._create_attachments(self._create_related_attachments(self._create_alternatives(msg))) def _create_alternatives(self, msg): for i, (content, mimetype) in enumerate(self.alternatives): if mimetype == 'text/html': for filename, _, _ in self.related_attachments: content = re.sub(r'(?' % filename) return attachment