Sending attachment in HTML email with Python

email, email-attachments, html, python

Solution

To have text, html and attachments at the same time it is necessary to use both mixed and alternative parts.

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText

text = "This is the plain text version."
html = "<html><p>This is some HTML</p></html>"
text_part = MIMEText(text, 'plain')
html_part = MIMEText(html, 'html')

msg_alternative = MIMEMultipart('alternative')
msg_alternative.attach(text_part)
msg_alternative.attach(html_part)

filename='graph.pdf'
fp=open(filename,'rb')
attachment = email.mime.application.MIMEApplication(fp.read(),_subtype="pdf")
fp.close()
attachment.add_header('Content-Disposition', 'attachment', filename=filename)

msg_mixed = MIMEMultipart('mixed')
msg_mixed.attach(msg_alternative)
msg_mixed.attach(attachment)
msg_mixed['From'] = 'me@gmail.com'
msg_mixed['To'] = 'you@gmail.com'
msg_mixed['Subject'] = 'Deliverability Report'

smtp_obj = smtplib.SMTP('SERVER', port=25)
smtp_obj.ehlo()
smtp_obj.login('NAME', 'PASSWORD')
smtp_obj.sendmail(msg_mixed['From'], msg_mixed['To'], msg_mixed.as_string())
smtp_obj.quit()

Message structure should be like this:

Mixed:

- Alternative:

- Text

- HTML

- Attachment

Problem

I saw there are a few somewhat similar questions on stack overflow already, but I couldn't find a solution to my specific problem in them. I am trying to use Python to send an HTML email with a .pdf attachment. It seems to work fine when I check my email on gmail.com, but when I check the message through apple's Mail program, I do not see the attachment. Any idea what is causing this? My code is below. A lot of it is copied from various places on stack overflow, so I do not completely understand what each part is doing, but it seems to (mostly) work: ``` import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.application import MIMEApplication from os.path import basename import email import email.mime.application #plain text version text = "This is the plain text version." #html body html = """<html><p>This is some HTML</p></html>""" # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart('alternative') msg['Subject'] = "Deliverability Report" msg['From'] = "me@gmail.com" msg['To'] = "you@gmail.com" # Record the MIME types of both parts - text/plain and text/html part1 = MIMEText(text, 'plain') part2 = MIMEText(html, 'html') # create PDF attachment filename='graph.pdf' fp=open(filename,'rb') att = email.mime.application.MIMEApplication(fp.read(),_subtype="pdf") fp.close() att.add_header('Content-Disposition','attachment',filename=filename) # Attach parts into message container. msg.attach(att) msg.attach(part1) msg.attach(part2) # Send the message via local SMTP server. s = smtplib.SMTP() s.connect('smtp.webfaction.com') s.login('NAME','PASSWORD') s.sendmail(msg['From'], msg['To'], msg.as_string()) s.quit() ``` I'm not sure if it is relevant, but I am running this code on a WebFaction server. Thanks for the help!

Original source