How to send email through your Google account with Python

June 29, 2007

Seems like a pretty trivial task, yes?

Generally speaking, it is, but I ran into a few fun things that make this worth writing about.

Background:

I have a server-side process that I want to send a notice of completion to a customer (and his customer), so I can’t just send it from jobuser@server.example.com — I want it to look presentable.

On Solaris, the “mailx” command has the option to change the “From:” address, and that is usually enough to make an e-mail look decent and get past a lot of the relay blockers. I’ve not yet found a similar solution for Linux (although, I’m sure it’s there).

Instead, I wrote a small python script to do this for me. As a bonus, I want to send it through my Google Apps e-mail account (well, a special service account created for this purpose). Sending through Google has the other feature of it is less likely to get blacklisted by some random ISP as our corporate IPs get from time to time.

So, some code …

#
# Grab the smtp and mxDateTime (excellent Date/Time manipulation
# from eGenix) packages:
#
import smtplib
from mx.DateTime import *

#
# We want yesterday’s date
#
now = now() – RelativeDateTime(days=1)

YEAR = now.year
MONTH = now.month
DAY = now.day

#
# Define our GMail auth information
#
smtpuser = ‘service.account@example.com’
smtppass = ‘sekratpassword’

#
# We have to define the From, To, and BCC addresses
#
# Note the “toaddrs” needs to be set up with 2 different formats, depending
# where in the mail message it is used
#
fromaddr = ‘Service Account <service.account@example.com>’
toaddrs = ‘customer@customer.com, theircustomer@theircustomer.com’.split()
bccaddrs = ‘me@example.com’

#
# Build the subject line
#
subject = (“Report For %02d/%02d/%04d” % (MONTH, DAY, YEAR))

#
# Start building the message with the mail header … again, note the join() used
# on the toaddrs
#
# NOTE: the placement and number of “\r\n”s are important … if you do not follow
# the RFC, your e-mail won’t get very far!
#
msg = ("From: %s\r\nTo: %s\r\nBcc: %s\r\nSubject: %s\r\n\r\n" %
(fromaddr, ", ".join(toaddrs), bccaddrs, subject))

#
# Now append the body of the message.
#
msg += “Hello,\r\n\r\nYour report is available at:\r\n\r\n”
msg += ” http://www.example.com/report.php"
msg += "\r\n\r\nRespectfully,\r\n\r\nCustomer Name\r\n"

#
# Create an SMTP object with the server “smtp.gmail.com” (their outbound mailserver)
#
server = smtplib.SMTP(‘smtp.gmail.com’)

#
# Optional, but it gives you a nice view of the conversation for coding/debugging
# purposes
#
server.set_debuglevel(1)

#
# Start the conversation with EHLO
#
server.ehlo()
#
# Request STARTTLS
#
server.starttls()
#
# And say EHLO again
#
server.ehlo()
#
# Login to the server with SMTP AUTH now that we’re TLS’d and client identified
#
server.login(smtpuser, smtppass)
#
# Finally, send the mail!
#
server.sendmail(fromaddr, toaddrs, msg)
#
# Herein lies a hack to work around a bug in this version of python and the
# associated libs. Read more about it here and patch your version, or be lazy
# like me and just trap the Exception and move on with life. 🙂
#
try:
server.quit()
except:
pass

That’s it in a nutshell.

If I may go back and plug the mxDateTime package from eGenix again, and I may, it’s some nice stuff. They fill the gaps between what the standard python package starts to do and what you really want to do.

In our example above, to get yesterday’s date, it’s as simple as:

now = now() - RelativeDateTime(days=1)

Want the last Monday of the month?

LastMonday = now() + RelativeDateTime(day=28, weekday=(Monday,0))

Granted, that will give you the same time of day as when the line is run, but you can override that with adding the options to RelativeDateTime of:

hour=0, minute=0, second=0

or just use LastMonday.day

Fun stuff, I highly recommend their stuff (they have lots of fun packages)

add to del.icio.usDigg itStumble It!Add to Blinkslistadd to furladd to ma.gnoliaadd to simpyseed the vineTailRank

Advertisements