Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Update</strong></p> <p>Many thanks to <a href="https://stackoverflow.com/users/1742777/saqib-ali">Saqib Ali</a> for resurrecting this old question nearly 5 years after my reply. </p> <p>The instructions I gave at the time no longer work. I suspect there have been some improvements to Django in the intervening years which mean that <code>send_mail()</code> enforces plain text. No matter what you put in the content, it will always be delivered as plain text.</p> <p>The most recent <a href="https://docs.djangoproject.com/en/1.6/topics/email/#send-mail" rel="nofollow noreferrer">Django documentation</a> explains that <code>send_mail()</code> is really just a convenience for creating an instance of the <code>django.core.mail.EmailMessage</code> class, and then calling <code>send()</code> on that instance. <code>EmailMessage</code> has this note for the body parameter, which explains the results we're seeing now in 2014:</p> <blockquote> <p>body: The body text. This should be a plain text message.</p> <p>... somewhat later in the docs ...</p> <p>By default, the MIME type of the body parameter in an EmailMessage is "text/plain". It is good practice to leave this alone.</p> </blockquote> <p>Fair enough (I confess I haven't taken the time to investigate why the 2009 instructions worked - I did test them back in 2009 - or when it changed). Django does provide, and <a href="https://docs.djangoproject.com/en/1.6/topics/email/#sending-alternative-content-types" rel="nofollow noreferrer">document</a>, a <code>django.core.mail.EmailMultiAlternatives</code> class to make it easier for sending a plain text and HTML representation of the same message.</p> <p>The case in this question is slightly different. We're not seeking to append an alternative per se, but to append <em>related</em> parts to one of the alternatives. Within the HTML version (and it doesn't matter if you have or omit the plain text version), we want to embed an image data part. Not an alternative view of the content, but <em>related</em> content that is referenced in the HTML body.</p> <p>Sending an embedded image is still possible, but I don't see a straightforward way to do it using <code>send_mail</code>. It's time to dispense with the convenience function and to instantiate an <code>EmailMessage</code> directly. </p> <p>Here's an update to the previous example:</p> <pre><code>from django.core.mail import EmailMessage from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # Load the image you want to send as bytes img_data = open('logo.jpg', 'rb').read() # Create a "related" message container that will hold the HTML # message and the image. These are "related" (not "alternative") # because they are different, unique parts of the HTML message, # not alternative (html vs. plain text) views of the same content. html_part = MIMEMultipart(_subtype='related') # Create the body with HTML. Note that the image, since it is inline, is # referenced with the URL cid:myimage... you should take care to make # "myimage" unique body = MIMEText('&lt;p&gt;Hello &lt;img src="cid:myimage" /&gt;&lt;/p&gt;', _subtype='html') html_part.attach(body) # Now create the MIME container for the image img = MIMEImage(img_data, 'jpeg') img.add_header('Content-Id', '&lt;myimage&gt;') # angle brackets are important img.add_header("Content-Disposition", "inline", filename="myimage") # David Hess recommended this edit html_part.attach(img) # Configure and send an EmailMessage # Note we are passing None for the body (the 2nd parameter). You could pass plain text # to create an alternative part for this message msg = EmailMessage('Subject Line', None, 'foo@bar.com', ['bar@foo.com']) msg.attach(html_part) # Attach the raw MIMEBase descendant. This is a public method on EmailMessage msg.send() </code></pre> <hr> <p><strong>Original reply from 2009:</strong></p> <p>To send an e-mail with embedded images, use python's built-in email module to build up the MIME parts.</p> <p>The following should do it:</p> <pre><code>from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # Load the image you want to send at bytes img_data = open('logo.jpg', 'rb').read() # Create a "related" message container that will hold the HTML # message and the image msg = MIMEMultipart(_subtype='related') # Create the body with HTML. Note that the image, since it is inline, is # referenced with the URL cid:myimage... you should take care to make # "myimage" unique body = MIMEText('&lt;p&gt;Hello &lt;img src="cid:myimage" /&gt;&lt;/p&gt;', _subtype='html') msg.attach(body) # Now create the MIME container for the image img = MIMEImage(img_data, 'jpeg') img.add_header('Content-Id', '&lt;myimage&gt;') # angle brackets are important msg.attach(img) send_mail(subject, msg.as_string(), from, [to], priority="high") </code></pre> <p>In reality, you'll probably want to send the HTML along with a plain-text alternative. In that case, use MIMEMultipart to create the "related" mimetype container as the root. Then create another MIMEMultipart with the subtype "alternative", and attach both a MIMEText (subtype html) and a MIMEText (subtype plain) to the alternative part. Then attach the image to the related root.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload