Wednesday, August 22, 2007

Sending emails via Gmail with Python

Whenever I need to send files from work to home I use gmail. Usually this email message consists of one single file (that may be a tarball) and has the file name for subject. In the "Automate Everything" spirit, I decided to build a script to do this task for me.

The first thing I had to do was find out how to send an email with an attachment via gmail. It wasn't too hard to find this information around the web, but it still took me the best part of an hour. So here's a simple Python script that sends an email with an attachment:

#!/usr/bin/python

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os

gmail_user = "your_email@gmail.com"
gmail_pwd = "your_password"

def mail(to, subject, text, attach):
msg = MIMEMultipart()

msg['From'] = gmail_user
msg['To'] = to
msg['Subject'] = subject

msg.attach(MIMEText(text))

part = MIMEBase('application', 'octet-stream')
part.set_payload(open(attach, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition',
'attachment; filename="%s"' % os.path.basename(attach))
msg.attach(part)

mailServer = smtplib.SMTP("smtp.gmail.com", 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user, gmail_pwd)
mailServer.sendmail(gmail_user, to, msg.as_string())
# Should be mailServer.quit(), but that crashes...
mailServer.close()

mail("some.person@some.address.com",
"Hello from python!",
"This is a email sent with python",
"my_picture.jpg")

29 comments:

Sam said...

Yay! I need to do exactly this. Thank you so much for putting this recipe up here.

I'd written something similar using the old libgmail, but for whatever reason I can't get it working.

Thanks again!

alec said...

Awesome work, thanks.

Anonymous said...

There's a Nautilus script which allows us to send files to Gmail just right-clicking on the file and selecting "Send to Gmail".

It's called nautilus-send-gmail
http://mundogeek.net/nautilus-scripts/

Anonymous said...

Great !!!!

It works perfect.

Pierre said...

Thanks a lot! 3 minutes from googling to solving the issue, copy and paste included!

Thanks for posting this useful snippet.

Anonymous said...

Great peace of code.
Kudos to you my friend.

jont said...

Thanks of that it makes this logging app so much more useful
http://jamesoff.net/site/code/simplemonitor/

Anonymous said...

Thanks! Great script.
Adding command line options made it perfect for me: no options means the attachment is saved in my gmail account.
Very convenient.

Jyaif said...

daily database backup, here I come

Anonymous said...

Thanks - this is great and will save me a lot of time. I had it working in less than a minute.

cryptoj at yahoo dot com

Timur Izhbulatov said...

Well, at first glance I can't see how it differs from sending email through any other SMTP server. Is there anything gmail-specific I missed?

Josh said...

If I wasn't a guy, I would want to have your children.

Supriya said...

Awesome!
Million Thanks!!

Anonymous said...

This is good. Thank you. -A

Rico Chen said...

Hi this works great and the script would be more flexible if the attach becomes an optional argument:

def mail(to, subject, text,
attach=None):
  msg = MIMEMultipart()

  msg['From'] = gmail_user
  msg['To'] = to
  msg['Subject'] = subject

  msg.attach(MIMEText(text))
  if attach:
    part = MIMEBase('application', 'octet-stream')
    part.set_payload(open(attach, 'rb').read())
    Encoders.encode_base64(part)
    part.add_header('Content-Disposition',
'attachment; filename="%s"' % os.path.basename(attach))
    msg.attach(part)
...

mynthon said...

This is why python docs sux. This example should be there!

Thanx for grat script!

Anonymous said...

Works great! Thank you.

Nick said...

Thanks for this script, I used it to create a backup script for my dreamhost account. Read more on that on my blog.

Thanks again for sharing!

Björn said...

Hi, I tried this script at home (no proxy) and it works perfectly. At work, however, everything goes through a proxy server. I tried to find out how to adapt to that, but I didnt manage. Does anyone have a clue?
/bjorn

O said...

Great script!

I tried and the only change I had to make was to change the attach variable from "my_picture.jpg" to "/User/user_name_here/Desktop/FileName.jpg"

After that receiving the email with the picture in gmail was great!

Thanks!

Omar

Sirhc Senots said...
This post has been removed by the author.
Sirhc Senots said...

I used your function to write my Inbox Poem Sender. http://welcometochrisworld.com/2009/03/24/inbox-poem-program/ Thanks

Anonymous said...

Excellent script! Any ideas how to make it work with Python 3.0? Thanks!

Alex said...

Great Script! Thank you!

Lionel said...

Very nice! I love how this was easy to search for...didnt have to kill myself to figure out how to do this

Knight Samar said...

Hey, thanks a lot!

This helped me confirm that I was on the right path because smtp.gmail.com sprouted "Auth not supported" msgs many times.

Keep blogging!

Aldo said...

man you are a Haaaaaaaaaacker. Great script.

I have one question.
How to specify multiple recipients?

Kutuma said...

Thank you all for the great comments!

@bjorn: Sorry, don't know how to make it work via a proxy server... I googled a bit, but couldn't find an answer (but I did find your question plenty of times!)

@Anonymous: Haven't tried it in Python 3.0... still haven't made the leap! :)

@Aldo: Haven't tested several recipients, but I believe you can just separate them by commas. E.g. "first@blah.net, second@blah.net"

Aldo said...

maybee this helps:

import os
from urllib2 import urlopen

# example proxy
os.environ['HTTP_PROXY']='http://169.229.50.9:3128'
try:
f = urlopen('http://www.google.com')
data = f.read()
f.close()
print 'Pass'
except:
print 'Fail'