8

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!

user3658457
  • 275
  • 3
  • 11

2 Answers2

4

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
Filip Kwiatkowski
  • 615
  • 2
  • 9
  • 20
1

Use

msg = MIMEMultipart('mixed')

instead of 'alternative'

Georg Pfolz
  • 1,416
  • 2
  • 12
  • 12