Browse files

Added support for creating multipart/alternative email messages. Also…

… allow

tweaking of main body MIME subtype for brave people. Fixed #3605.

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 2d082a3 commit 719a90391d1d78194f18219dd434e662465c424d @malcolmt malcolmt committed Jun 27, 2007
Showing with 62 additions and 7 deletions.
  1. +26 −7 django/core/
  2. +36 −0 docs/email.txt
@@ -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): = to or []
@@ -185,10 +188,10 @@ def get_connection(self, fail_silently=False):
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:
for attachment in self.attachments:
@@ -216,14 +219,17 @@ def send(self, fail_silently=False):
"""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
assert content is not None
@@ -252,9 +258,22 @@ def _create_attachment(self, filename, content, mimetype=None):
attachment = MIMEBase(basetype, subtype)
- 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
@@ -281,6 +281,42 @@ The class has the following methods:
+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
+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 = "<p>This is an <strong>important</strong> 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

0 comments on commit 719a903

Please sign in to comment.