Ticket #9367: mail.py.patch

File mail.py.patch, 5.7 KB (added by loekje, 7 years ago)
  • mail.py

    old new  
    190190            return False
    191191        return True
    192192
     193""" http://code.djangoproject.com/ticket/9367 by Loek Engels """
    193194class EmailMessage(object):
    194195    """
    195196    A container for email information.
    196197    """
    197198    content_subtype = 'plain'
    198     multipart_subtype = 'mixed'
     199    mixed_subtype = 'mixed'
    199200    encoding = None     # None => use settings default
    200201
    201202    def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
     
    234235        encoding = self.encoding or settings.DEFAULT_CHARSET
    235236        msg = SafeMIMEText(smart_str(self.body, settings.DEFAULT_CHARSET),
    236237                           self.content_subtype, encoding)
    237         if self.attachments:
    238             body_msg = msg
    239             msg = SafeMIMEMultipart(_subtype=self.multipart_subtype)
    240             if self.body:
    241                 msg.attach(body_msg)
    242             for attachment in self.attachments:
    243                 if isinstance(attachment, MIMEBase):
    244                     msg.attach(attachment)
    245                 else:
    246                     msg.attach(self._create_attachment(*attachment))
     238        msg = self._create_message(msg)
    247239        msg['Subject'] = self.subject
    248240        msg['From'] = self.from_email
    249241        msg['To'] = ', '.join(self.to)
     
    267259    def attach(self, filename=None, content=None, mimetype=None):
    268260        """
    269261        Attaches a file with the given filename and content. The filename can
    270         be omitted (useful for multipart/alternative messages) and the mimetype
    271         is guessed, if not provided.
     262        be omitted and the mimetype is guessed, if not provided.
    272263
    273264        If the first parameter is a MIMEBase subclass it is inserted directly
    274265        into the resulting message attachments.
     
    286277        content = open(path, 'rb').read()
    287278        self.attach(filename, content, mimetype)
    288279
    289     def _create_attachment(self, filename, content, mimetype=None):
    290         """
    291         Converts the filename, content, mimetype triple into a MIME attachment
    292         object.
     280    def _create_message(self, msg):
     281        return self._create_attachments(msg)
     282
     283    def _create_attachments(self, msg):
     284        if self.attachments:
     285            body_msg = msg
     286            msg = SafeMIMEMultipart(_subtype=self.mixed_subtype)
     287            if self.body:
     288                msg.attach(body_msg)
     289            for attachment in self.attachments:
     290                if isinstance(attachment, MIMEBase):
     291                    msg.attach(attachment)
     292                else:
     293                    msg.attach(self._create_attachment(*attachment))
     294        return msg
     295
     296    def _create_mime_attachment(self, content, mimetype):
     297        """
     298        Converts the content, mimetype pair into a MIME attachment object.
    293299        """
    294         if mimetype is None:
    295             mimetype, _ = mimetypes.guess_type(filename)
    296             if mimetype is None:
    297                 mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
    298300        basetype, subtype = mimetype.split('/', 1)
    299301        if basetype == 'text':
    300302            attachment = SafeMIMEText(smart_str(content,
     
    304306            attachment = MIMEBase(basetype, subtype)
    305307            attachment.set_payload(content)
    306308            Encoders.encode_base64(attachment)
     309        return attachment
     310
     311    def _create_attachment(self, filename, content, mimetype=None):
     312        """
     313        Converts the filename, content, mimetype triple into a MIME attachment
     314        object.
     315        """
     316        if mimetype is None:
     317            mimetype, _ = mimetypes.guess_type(filename)
     318            if mimetype is None:
     319                mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
     320        attachment = self._create_mime_attachment(content, mimetype)
    307321        if filename:
    308322            attachment.add_header('Content-Disposition', 'attachment',
    309323                                  filename=filename)
     
    315329    messages. For example, including text and HTML versions of the text is
    316330    made easier.
    317331    """
    318     multipart_subtype = 'alternative'
     332    alternative_subtype = 'alternative'
     333
     334    def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
     335            connection=None, attachments=None, headers=None, alternatives=None):
     336        """
     337        Initialize a single email message (which can be sent to multiple
     338        recipients).
     339
     340        All strings used to create the message can be unicode strings (or UTF-8
     341        bytestrings). The SafeMIMEText class will handle any necessary encoding
     342        conversions.
     343        """
     344        super(EmailMultiAlternatives, self).__init__(subject, body, from_email, to, bcc, connection, attachments, headers)
     345        self.alternatives=alternatives or []
    319346
    320     def attach_alternative(self, content, mimetype=None):
     347    def attach_alternative(self, content, mimetype):
    321348        """Attach an alternative content representation."""
    322         self.attach(content=content, mimetype=mimetype)
     349        assert content is not None
     350        assert mimetype is not None
     351        self.alternatives.append((content, mimetype))
     352
     353    def _create_message(self, msg):
     354        return self._create_attachments(self._create_alternatives(msg))
     355
     356    def _create_alternatives(self, msg):
     357        if self.alternatives:
     358            body_msg = msg
     359            msg = SafeMIMEMultipart(_subtype=self.alternative_subtype)
     360            if self.body:
     361                msg.attach(body_msg)
     362            for alternative in self.alternatives:
     363                msg.attach(self._create_mime_attachment(*alternative))
     364        return msg
    323365
    324366def send_mail(subject, message, from_email, recipient_list,
    325367              fail_silently=False, auth_user=None, auth_password=None):
Back to Top