Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending attachment in HTML email with Python

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'] = "[email protected]"
msg['To'] = "[email protected]"

# 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!

like image 774
user3658457 Avatar asked Oct 26 '16 19:10

user3658457


People also ask

How do you send an attachment in HTML?

For html emails you have to set this in the header of the email content-type: text/html . However, if you want to send an attachment you have to change it to content-type: multipart/mixed . Which would make the html email...not html anymore.


1 Answers

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'] = '[email protected]'
msg_mixed['To'] = '[email protected]'
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
like image 163
Filip Kwiatkowski Avatar answered Oct 01 '22 20:10

Filip Kwiatkowski