Sending Multipart html emails which contain embedded images Sending Multipart html emails which contain embedded images python python

Sending Multipart html emails which contain embedded images


Here is an example I found.

Recipe 473810: Send an HTML email with embedded image and plain text alternate:

HTML is the method of choice for thosewishing to send emails with rich text,layout and graphics. Often it isdesirable to embed the graphics withinthe message so recipients can displaythe message directly, without furtherdownloads.

Some mail agents don't support HTML ortheir users prefer to receive plaintext messages. Senders of HTMLmessages should include a plain textmessage as an alternate for theseusers.

This recipe sends a short HTML messagewith a single embedded image and analternate plain text message.

# 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 MIMEMultipartfrom email.MIMEText import MIMETextfrom 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 headersmsgRoot = MIMEMultipart('related')msgRoot['Subject'] = 'test message'msgRoot['From'] = strFrommsgRoot['To'] = strTomsgRoot.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 belowmsgText = 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 directoryfp = open('test.jpg', 'rb')msgImage = MIMEImage(fp.read())fp.close()# Define the image's ID as referenced abovemsgImage.add_header('Content-ID', '<image1>')msgRoot.attach(msgImage)# Send the email (this example assumes SMTP authentication is required)import smtplibsmtp = smtplib.SMTP()smtp.connect('smtp.example.com')smtp.login('exampleuser', 'examplepass')smtp.sendmail(strFrom, strTo, msgRoot.as_string())smtp.quit()


For Python versions 3.4 and above.

The accepted answer is excellent, but only suitable for older Python versions (2.x and 3.3). I think it needs an update.

Here's how you can do it in newer Python versions (3.4 and above):

from email.message import EmailMessagefrom email.utils import make_msgidimport mimetypesmsg = EmailMessage()# generic email headersmsg['Subject'] = 'Hello there'msg['From'] = 'ABCD <abcd@xyz.com>'msg['To'] = 'PQRS <pqrs@xyz.com>'# set the plain text bodymsg.set_content('This is a plain text body.')# now create a Content-ID for the imageimage_cid = make_msgid(domain='xyz.com')# if `domain` argument isn't provided, it will # use your computer's name# set an alternative html bodymsg.add_alternative("""\<html>    <body>        <p>This is an HTML body.<br>           It also has an image.        </p>        <img src="cid:{image_cid}">    </body></html>""".format(image_cid=image_cid[1:-1]), subtype='html')# image_cid looks like <long.random.number@xyz.com># to use it as the img src, we don't need `<` or `>`# so we use [1:-1] to strip them off# now open the image and attach it to the emailwith open('path/to/image.jpg', 'rb') as img:    # know the Content-Type of the image    maintype, subtype = mimetypes.guess_type(img.name)[0].split('/')    # attach it    msg.get_payload()[1].add_related(img.read(),                                          maintype=maintype,                                          subtype=subtype,                                          cid=image_cid)# the message is ready now# you can write it to a file# or send it using smtplib


Code working

    att = MIMEImage(imgData)    att.add_header('Content-ID', f'<image{i}.{imgType}>')    att.add_header('X-Attachment-Id', f'image{i}.{imgType}')    att['Content-Disposition'] = f'inline; filename=image{i}.{imgType}'    msg.attach(att)