Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit 719a90391d1d78194f18219dd434e662465c424d 1 parent 2d082a3
Malcolm Tredinnick authored June 27, 2007
33  django/core/mail.py
@@ -169,6 +169,9 @@ class EmailMessage(object):
169 169
     """
170 170
     A container for email information.
171 171
     """
  172
+    content_subtype = 'plain'
  173
+    multipart_subtype = 'mixed'
  174
+
172 175
     def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
173 176
             connection=None, attachments=None):
174 177
         self.to = to or []
@@ -185,10 +188,10 @@ def get_connection(self, fail_silently=False):
185 188
         return self.connection
186 189
 
187 190
     def message(self):
188  
-        msg = SafeMIMEText(self.body, 'plain', settings.DEFAULT_CHARSET)
  191
+        msg = SafeMIMEText(self.body, self.content_subtype, settings.DEFAULT_CHARSET)
189 192
         if self.attachments:
190 193
             body_msg = msg
191  
-            msg = SafeMIMEMultipart()
  194
+            msg = SafeMIMEMultipart(_subtype=self.multipart_subtype)
192 195
             if self.body:
193 196
                 msg.attach(body_msg)
194 197
             for attachment in self.attachments:
@@ -216,14 +219,17 @@ def send(self, fail_silently=False):
216 219
         """Send the email message."""
217 220
         return self.get_connection(fail_silently).send_messages([self])
218 221
 
219  
-    def attach(self, filename, content=None, mimetype=None):
  222
+    def attach(self, filename=None, content=None, mimetype=None):
220 223
         """
221  
-        Attaches a file with the given filename and content.
  224
+        Attaches a file with the given filename and content. The filename can
  225
+        be omitted (useful for multipart/alternative messages) and the mimetype
  226
+        is guessed, if not provided.
222 227
 
223  
-        Alternatively, the first parameter can be a MIMEBase subclass, which
224  
-        is inserted directly into the resulting message attachments.
  228
+        If the first parameter is a MIMEBase subclass it is inserted directly
  229
+        into the resulting message attachments.
225 230
         """
226 231
         if isinstance(filename, MIMEBase):
  232
+            assert content == mimetype == None
227 233
             self.attachements.append(filename)
228 234
         else:
229 235
             assert content is not None
@@ -252,9 +258,22 @@ def _create_attachment(self, filename, content, mimetype=None):
252 258
             attachment = MIMEBase(basetype, subtype)
253 259
             attachment.set_payload(content)
254 260
             Encoders.encode_base64(attachment)
255  
-        attachment.add_header('Content-Disposition', 'attachment', filename=filename)
  261
+        if filename:
  262
+            attachment.add_header('Content-Disposition', 'attachment', filename=filename)
256 263
         return attachment
257 264
 
  265
+class EmailMultiAlternatives(EmailMessage):
  266
+    """
  267
+    A version of EmailMessage that makes it easy to send multipart/alternative
  268
+    messages. For example, including text and HTML versions of the text is
  269
+    made easier.
  270
+    """
  271
+    multipart_subtype = 'alternative'
  272
+
  273
+    def attach_alternative(self, content, mimetype=None):
  274
+        """Attach an alternative content representation."""
  275
+        self.attach(content=content, mimetype=mimetype)
  276
+
258 277
 def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None):
259 278
     """
260 279
     Easy wrapper for sending a single message to a recipient list. All members
36  docs/email.txt
@@ -281,6 +281,42 @@ The class has the following methods:
281 281
 
282 282
         message.attach_file('/images/weather_map.png')
283 283
 
  284
+Sending alternative content types
  285
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  286
+
  287
+It is often useful to include multiple versions of the content in an e-mail.
  288
+For instance, sending both text and HTML versions of an e-mail. You can do
  289
+this using the ``EmailMultiAlternatives`` class. This sub-class of
  290
+``EmailMessage`` has an ``attach_alternative()`` method for including
  291
+extra versions of the message body in the e-mail. All the other methods
  292
+(including the class initialization) are inherited directly from
  293
+``EmailMessage``.
  294
+
  295
+To send a text and HTML combination, you could write::
  296
+
  297
+    from django.core.mail import EmailMultiAlternatives
  298
+
  299
+    subject, from_email, to = ...
  300
+    text_content = "This is an important message."
  301
+    html_content = "<p>This is an <strong>important</strong> message."
  302
+    msg = EmailMultiAlternatives(subject, text_content, from_email, to)
  303
+    msg.attach_alternative(html_content, "text/html")
  304
+    msg.send()
  305
+
  306
+
  307
+
  308
+By default, the MIME type of the ``body`` parameter in an ``EmailMessage`` is
  309
+``"text/plain"``. It is good practice to leave this alone, since it guarantees
  310
+that any recipient will be able to read the e-mail, regardless of their mail
  311
+client. However, if you are confident that your recipients can handle an
  312
+alternative content type, you can use the ``content_subtype`` attribute on the
  313
+``EmailMessage`` class to change the main content type. The major type will
  314
+always be ``"text"``, but you can change to the subtype. For example::
  315
+
  316
+    msg = EmailMessage(subject, html_content, from_email, to)
  317
+    msg.content_subtype = "html"  # Main content is now text/html
  318
+    msg.send()
  319
+
284 320
 SMTP network connections
285 321
 -------------------------
286 322
 

0 notes on commit 719a903

Please sign in to comment.
Something went wrong with that request. Please try again.