Welcome, guest | Sign In | My Account | Store | Cart

HTML is the method of choice for those wishing to send emails with rich text, layout and graphics. Often it is desirable to embed the graphics within the message so recipients can display the message directly, without further downloads.

Some mail agents don't support HTML or their users prefer to receive plain text messages. Senders of HTML messages should include a plain text message as an alternate for these users.

This recipe sends a short HTML message with a single embedded image and an alternate plain text message.

Python, 46 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Send an HTML email with an embedded image and a plain text message for
# email clients that don't want to display the HTML.

from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage

# Define these once; use them twice!
strFrom = 'from@example.com'
strTo = 'to@example.com'

# Create the root message and fill in the from, to, and subject headers
msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = 'test message'
msgRoot['From'] = strFrom
msgRoot['To'] = strTo
msgRoot.preamble = 'This is a multi-part message in MIME format.'

# Encapsulate the plain and HTML versions of the message body in an
# 'alternative' part, so message agents can decide which they want to display.
msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)

msgText = MIMEText('This is the alternative plain text message.')
msgAlternative.attach(msgText)

# We reference the image in the IMG SRC attribute by the ID we give it below
msgText = MIMEText('<b>Some <i>HTML</i> text</b> and an image.<br><img src="cid:image1"><br>Nifty!', 'html')
msgAlternative.attach(msgText)

# This example assumes the image is in the current directory
fp = open('test.jpg', 'rb')
msgImage = MIMEImage(fp.read())
fp.close()

# Define the image's ID as referenced above
msgImage.add_header('Content-ID', '<image1>')
msgRoot.attach(msgImage)

# Send the email (this example assumes SMTP authentication is required)
import smtplib
smtp = smtplib.SMTP()
smtp.connect('smtp.example.com')
smtp.login('exampleuser', 'examplepass')
smtp.sendmail(strFrom, strTo, msgRoot.as_string())
smtp.quit()

While the practice of embedding images within the message provides a better experience for many users than linking to web-hosted images does it is important to consider the impact this has on message size and consequently on message download time.

An alternative implementation for sending HTML messages is provided in this recipe http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/67083, though it doesn't address embedding images and was written before the email package was incorporated into Python. The email package and its MIME-handling capabilities significantly reduce the amount of code required.

10 comments

Sean b 18 years, 3 months ago  # | flag

Nice and simple example to embed images in HTML mails.

Thanks for sharing

Simon Tite 16 years, 5 months ago  # | flag

Just what I was looking for... Many thanks, this is just what I needed, after spending hours searching for some sort of mail user agent that could automate the process of sending invoices to customers bye e-mail. Invoices need a company logo, don't they? Hence the need for embedding a small graphic in the text..

Trent Mick 14 years, 10 months ago  # | flag

Thanks for this. This helped me put together recipe 576824 for sending a multipart email via gmail.

Jesse Hogan 14 years, 8 months ago  # | flag

Be sure to not call your test email script 'email.py' or it will conflict with the email package.

Mark Engstrom 14 years, 3 months ago  # | flag

When setting the msgRoot['To'] = strTo header, what is the correct syntax if strTo is a list object of multiple recipients?

Mark Engstrom 14 years, 3 months ago  # | flag

nevermind ... found it : msgRoot['To'] = ", ".join(strTo)

Virginia 13 years, 10 months ago  # | flag

Hi Darrin, i have a question for you. i am not a pro, just html and graphic design with basic knowledge how to insert scripts. is this script you wrote in 2006 still valid?

i am looking for a way to insert the alternative txt within my email template design when html view is blocked in an email.

embedding an image means that the image will download/show regardless of the blockage email portals use?

is this code you programed what i need? if it is, where do i insert it within my html page design? can i control the text to indicate each line or a paragraph by inserting the <br> tags?

thank you!!

abraham katamba 11 years, 3 months ago  # | flag

Is this site for only python solutions? because i do not use python. but i would like to know how to send a picture mail for my newsletters using my ordinary mail form written in html. so that means i have to send it using the text area of the html form.

Slim ELABED 8 years, 9 months ago  # | flag

Very usefull post,

Thanks a lot !

Aleister Williams 7 years, 4 months ago  # | flag

I had connection errors with the code you posted, so I changed the server connection from this:

smtp = smtplib.SMTP()
smtp.connect('smtp.example.com')
smtp.login('exampleuser', 'examplepass')
smtp.sendmail(strFrom, strTo, msgRoot.as_string())
smtp.quit()

To this:

smtp = smtplib.SMTP('smtp.example.com',587)
smtp.starttls()
smtp.login('exampleuser','examplepass')
smtp.sendmail(strFrom,strTo,msgRoot.as_string())
smtp.quit()

and it worked wonderfully, in case anyone else has connection problems