From 719a90391d1d78194f18219dd434e662465c424d Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Wed, 27 Jun 2007 12:18:05 +0000 Subject: [PATCH] Added support for creating multipart/alternative email messages. Also allow tweaking of main body MIME subtype for brave people. Fixed #3605. git-svn-id: http://code.djangoproject.com/svn/django/trunk@5548 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/mail.py | 33 ++++++++++++++++++++++++++------- docs/email.txt | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/django/core/mail.py b/django/core/mail.py index 9c63569efa..cf8b5fec13 100644 --- a/django/core/mail.py +++ b/django/core/mail.py @@ -169,6 +169,9 @@ class EmailMessage(object): """ A container for email information. """ + content_subtype = 'plain' + multipart_subtype = 'mixed' + def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, connection=None, attachments=None): self.to = to or [] @@ -185,10 +188,10 @@ class EmailMessage(object): return self.connection def message(self): - msg = SafeMIMEText(self.body, 'plain', settings.DEFAULT_CHARSET) + msg = SafeMIMEText(self.body, self.content_subtype, settings.DEFAULT_CHARSET) if self.attachments: body_msg = msg - msg = SafeMIMEMultipart() + msg = SafeMIMEMultipart(_subtype=self.multipart_subtype) if self.body: msg.attach(body_msg) for attachment in self.attachments: @@ -216,14 +219,17 @@ class EmailMessage(object): """Send the email message.""" return self.get_connection(fail_silently).send_messages([self]) - def attach(self, filename, content=None, mimetype=None): + def attach(self, filename=None, content=None, mimetype=None): """ - Attaches a file with the given filename and content. + Attaches a file with the given filename and content. The filename can + be omitted (useful for multipart/alternative messages) and the mimetype + is guessed, if not provided. - Alternatively, the first parameter can be a MIMEBase subclass, which - is inserted directly into the resulting message attachments. + If the first parameter is a MIMEBase subclass it is inserted directly + into the resulting message attachments. """ if isinstance(filename, MIMEBase): + assert content == mimetype == None self.attachements.append(filename) else: assert content is not None @@ -252,9 +258,22 @@ class EmailMessage(object): attachment = MIMEBase(basetype, subtype) attachment.set_payload(content) Encoders.encode_base64(attachment) - attachment.add_header('Content-Disposition', 'attachment', filename=filename) + if filename: + attachment.add_header('Content-Disposition', 'attachment', filename=filename) return attachment +class EmailMultiAlternatives(EmailMessage): + """ + A version of EmailMessage that makes it easy to send multipart/alternative + messages. For example, including text and HTML versions of the text is + made easier. + """ + multipart_subtype = 'alternative' + + def attach_alternative(self, content, mimetype=None): + """Attach an alternative content representation.""" + self.attach(content=content, mimetype=mimetype) + def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None): """ Easy wrapper for sending a single message to a recipient list. All members diff --git a/docs/email.txt b/docs/email.txt index 3868387884..4d010efaf3 100644 --- a/docs/email.txt +++ b/docs/email.txt @@ -281,6 +281,42 @@ The class has the following methods: message.attach_file('/images/weather_map.png') +Sending alternative content types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is often useful to include multiple versions of the content in an e-mail. +For instance, sending both text and HTML versions of an e-mail. You can do +this using the ``EmailMultiAlternatives`` class. This sub-class of +``EmailMessage`` has an ``attach_alternative()`` method for including +extra versions of the message body in the e-mail. All the other methods +(including the class initialization) are inherited directly from +``EmailMessage``. + +To send a text and HTML combination, you could write:: + + from django.core.mail import EmailMultiAlternatives + + subject, from_email, to = ... + text_content = "This is an important message." + html_content = "

This is an important message." + msg = EmailMultiAlternatives(subject, text_content, from_email, to) + msg.attach_alternative(html_content, "text/html") + msg.send() + + + +By default, the MIME type of the ``body`` parameter in an ``EmailMessage`` is +``"text/plain"``. It is good practice to leave this alone, since it guarantees +that any recipient will be able to read the e-mail, regardless of their mail +client. However, if you are confident that your recipients can handle an +alternative content type, you can use the ``content_subtype`` attribute on the +``EmailMessage`` class to change the main content type. The major type will +always be ``"text"``, but you can change to the subtype. For example:: + + msg = EmailMessage(subject, html_content, from_email, to) + msg.content_subtype = "html" # Main content is now text/html + msg.send() + SMTP network connections -------------------------