Python Snippet: Sending HTML email with an attachment via Google Apps SMTP (or Gmail)
This is just one of those things that I had to do in a project (as part of a much bigger system), and wish I had it all laid out for me like this when I was writing it.
I broke it down into simple input variables that need to be filled out, and then let 'er rip.
You supply the account credentials, to address, from address, subject, HTML body (will be converted to plain as well, in case the email reader cannot support HTML for whatever reason), etc and everything else gets taken care of.
Should be easy to take the whole thing and throw it into a loop from a DB resultset, or something of that nature.
I initially wrote it to be used as part of a system that sent out different versions of "welcome" emails, as well as automated follow-up emails based on customer data and bunch of other shit. Fun times!
You're WELCOME!
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
#attachmentname = 'C:\\python27\\email.log' #path to an attachment, if you wish
username = 'someguy@mygoogleapps-or-gmail.com'
password = 'superSECRETdinoCLUBpasswords!!'
fromaddr = 'Some Guy <someguy@mygoogleapps-or-gmail.com>' #must be a vaild 'from' addy in your GApps account
toaddr = 'someoneelse@eelsandheels.com'
replyto = fromaddr #unless you want a different reply-to
msgsubject = 'This is for sexy email subjektz!'
htmlmsgtext = """This is my message body in HTML<br/>
Yup. Yup. Yup.</br>
<b>Done!</a>"""
#ok, here goes nothing
try:
msgtext = htmlmsgtext.replace('<b>','').replace('</b>','').replace('<br>',"\r").replace('</br>',"\r").replace('<br/>',"\r").replace('</a>','')
msgtext = re.sub('<.*?>','',msgtext)
#pain the ass mimey stuff
msg = MIMEMultipart()
msg.preamble = 'This is a multi-part message in MIME format.\n'
msg.epilogue = ''
body = MIMEMultipart('alternative')
body.attach(MIMEText(msgtext))
body.attach(MIMEText(htmlmsgtext, 'html'))
msg.attach(body)
if 'attachmentname' in globals(): #DO WE HAZ ATTACHMENT?
f = attachmentname
part = MIMEBase('application', "octet-stream")
part.set_payload( open(f,"rb").read() )
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
msg.add_header('From', fromaddr)
msg.add_header('To', toaddr)
##msg.add_header('Cc', ccaddy) #doesn't work apparently
##msg.add_header('Bcc', bccaddy) #doesn't work apparently
msg.add_header('Subject', msgsubject)
msg.add_header('Reply-To', replyto)
# The actual email sendy bits
server = smtplib.SMTP('smtp.gmail.com:587')
server.set_debuglevel(True) #commenting this out, changing to False will make the script give NO output at all upon successful completion
server.starttls()
server.login(username,password)
server.sendmail(msg['From'], [msg['To']], msg.as_string())
server.quit() #bye bye
except:
print ('Email NOT sent to %s successfully. %s ERR: %s %s %s ', str(toaddr), 'tete', str(sys.exc_info()[0]), str(sys.exc_info()[1]), str(sys.exc_info()[2]) )
#just in case
Sample Output
reply: '250-mx.google.com at your service, [67.248.53.114]\r\n'
reply: '250-SIZE 35882577\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-STARTTLS\r\n'
reply: '250 ENHANCEDSTATUSCODES\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [67.248.53.114]
SIZE 35882577
8BITMIME
STARTTLS
ENHANCEDSTATUSCODES
send: 'STARTTLS\r\n'
reply: '220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: 2.0.0 Ready to start TLS
send: 'ehlo [0.0.0.0]\r\n'
reply: '250-mx.google.com at your service, [67.248.53.114]\r\n'
reply: '250-SIZE 35882577\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-AUTH LOGIN PLAIN XOAUTH\r\n'
reply: '250 ENHANCEDSTATUSCODES\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [67.248.53.114]
SIZE 35882577
8BITMIME
AUTH LOGIN PLAIN XOAUTH
ENHANCEDSTATUSCODES
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted
send: 'mail FROM:<emailpeep@whatever.com> size=878\r\n'
reply: '250 2.1.0 OK bo5sm543779qab.1\r\n'
reply: retcode (250); Msg: 2.1.0 OK bo5sm543779qab.1
send: 'rcpt TO:<emailpeep@whatever.com>\r\n'
reply: '250 2.1.5 OK bo5sm543779qab.1\r\n'
reply: retcode (250); Msg: 2.1.5 OK bo5sm543779qab.1
send: 'data\r\n'
reply: '354 Go ahead bo5sm543779qab.1\r\n'
reply: retcode (354); Msg: Go ahead bo5sm543779qab.1
data: (354, 'Go ahead bo5sm543779qab.1')
send: 'Content-Type: multipart/mixed; boundary="===============0988883067=="\r\nMIME-Version: 1.0\r\nFrom: Some Guy <emailpeep@whatever.com>\r\nTo: emailpeep@whatever.com\r\nSubject: This is for sexy email su
bjektz!\r\nReply-To: Some Guy <emailpeep@whatever.com>\r\n\r\nThis is a multi-part message in MIME format.\r\n\r\n--===============0988883067==\r\nContent-Type: multipart/alternative; boundary="===============13
70445963=="\r\nMIME-Version: 1.0\r\n\r\n--===============1370445963==\r\nContent-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis is my message body in HTML\r
\n\t\t\t\tYup. Yup. Yup.\r\n\t\t\t\tDone!\r\n--===============1370445963==\r\nContent-Type: text/html; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\nThis is my message body in HT
ML<br/>\r\n\t\t\t\tYup. Yup. Yup.</br>\r\n\t\t\t\t<b>Done!</a>\r\n--===============1370445963==--\r\n--===============0988883067==--\r\n.\r\n'
reply: '250 2.0.0 OK 1343338799 bo5sm543779qab.1\r\n'
reply: retcode (250); Msg: 2.0.0 OK 1343338799 bo5sm543779qab.1
data: (250, '2.0.0 OK 1343338799 bo5sm543779qab.1')
send: 'quit\r\n'
reply: '221 2.0.0 closing connection bo5sm543779qab.1\r\n'
reply: retcode (221); Msg: 2.0.0 closing connection bo5sm543779qab.1