Playing With Python And Gmail

python In addition to its web interface Google also provides access via IMAP. The python imaplib module defines three classes, IMAP4, IMAP4_SSL and IMAP4_stream, which encapsulate a connection to an IMAP4 server and implement a large subset of the IMAP4rev1 client protocol as defined in RFC 2060.

The IMAP4 class implements the actual IMAP4 protocol. The connection is created and protocol version (IMAP4 or IMAP4rev1) is determined when the instance is initialized.

Getting started with Python Imaplib
To start with, we will create a simple python program to login to Gmail via IMAP.

import imaplib
rc, resp = M.login('', 'pa$$word')
print rc, resp

IMAP4.IMAP4_SSL is a subclass derived from IMAP4 that connects over an SSL encrypted socket (to use this class you need a socket module that was compiled with SSL support). If host is not specified, ” (the local host) is used. If port is omitted, the standard IMAP4-over-SSL port (993) is used. keyfile and certfile are also optional – they can contain a PEM formatted private key and certificate chain file for the SSL connection.

If authentication is successful the output will be:

OK [' authenticated (Success)']

As part of our exercise we will be writing may usefull functions. It is good to create a python class file to put our functions so that at the end of our exercise we will have a cool python gmail library. Lets create a

import imaplib
class pygmail:
  def __init__(self):
    self.M = None
    self.response = None
  def login(self, username, password):
    self.M = imaplib.IMAP4_SSL(self.IMAP_SERVER, self.IMAP_PORT)
    rc, self.response = self.M.login(username, password)
    return rc
  def logout(self):
g = pygmail()
g.login('', 'pa$$word')
print g.response

Listing Mailboxes
The IMAP4.list() function list mailbox names in directory matching pattern. The directory defaults to the top-level mail folder, and pattern defaults to match anything. Returned data contains a list of LIST responses.

Add the below function to our

def get_mailboxes(self):
  rc, self.response = self.M.list()
  for item in self.response:
  return rc


for item in g.mailboxes:
  print item

This will output your Gmail mailboxes


Creating, Renaming, Deleting Mailboxes
IMAP4.create, IMAP4.rename, IMAP4.delete functions will create, rename, delete the mailboxes respectively.
Lets add three more functions to out lib.

def rename_mailbox(self, oldmailbox, newmailbox):
  rc, self.response = self.M.rename(oldmailbox, newmailbox)
  return rc
def create_mailbox(self, mailbox):
  rc, self.response = self.M.create(mailbox)
  return rc
def delete_mailbox(self, mailbox):
  rc, self.response = self.M.delete(mailbox)
  return rc

Get Mail Count
The function select a mailbox. Returned data is the count of messages in mailbox (EXISTS response). The default mailbox is ‘INBOX’. If the readonly flag is set, modifications to the mailbox are not allowed.

Add the get_mail_count function to out Python class.

  def get_mail_count(self, folder='Inbox'):
    rc, count =
    return count[0]



You can specify your mailbox also.


Get Unread Mail Count
The IMAP4.status() function request named status conditions for mailbox. The standard defines these status conditions:

MESSAGES – The number of messages in the mailbox.
RECENT – The number of messages with the Recent flag set.
UIDNEXT – The next unique identifier value of the mailbox.
UIDVALIDITY – The unique identifier validity value of the mailbox.
UNSEEN – The number of messages which do not have the Seen flag set.

Using the UNSEEN condition will return total unread messages in Inbox.

Lets define a function to get unread mail count in our

  def get_unread_count(self, folder='Inbox'):
    rc, message = self.M.status(folder, "(UNSEEN)")
    unreadCount ="UNSEEN (\d+)", message[0]).group(1)
    return unreadCount



OK, enough for a start. In the next parts of this article I will explain sending, searching, retrieving mails from Gmail via Python. So dont forget to subscribe 🙂

I am pushing our small Python Gmail library to github hopefully useful to someone.


zoobert July 29, 2010

What would be nice is how to use the gmail api to activate some of the options like forwarding.

I would like to have a cron that activate the forwarding of gmail emails to my work account that is link to my blackberry in the evening when I am commuting home.

Some examples on how to play with the API would be beneficial.

Chris July 30, 2010

Great article, one code typo…

def logout(): should probably be def logout(self):

segfault July 30, 2010


Thanks for pointing that out.

Rohan Perera August 11, 2010

Do you have a method to retrieve the following from an email message:

1) subject
2) author
3) message of the email


segfault August 11, 2010

Yes. the below code will get the very first mail in your gmail inbox.

from email.parser import HeaderParser

data = M.FETCH(1, ‘(RFC822)’)
header_data = data[1][0][1]
parser = HeaderParser()
msg = parser.parsestr(header_data)

print msg[‘From’]
print msg[‘To’]
print msg[‘Subject’]

# get content
for part in msg.walk():
print part.get_content_type()
print part.get_payload()

hope this help.

mohammed mansoor kpa September 23, 2010

its more helpful
using ur code,only selected mails are retrieved but not other…
check that…

Esteban December 4, 2010

Is there any way to download attachments? Thanks for your post

sd December 29, 2010


thanks very much for the blog! – it is really useful.
I’m trying to connect to gmail using your code – but keep getting the same error:
“error: [Errno 10054] An existing connection was forcibly closed by the remote host”

do you know what this means?


Jim February 2, 2011

Nice work thanks for posting. A couple things I came across while using it.

def get_mailboxes(self):
rc, self.response = self.M.list()
for item in self.response:
shItem = shlex.split(item)
#Original, breaks on any label that has a space in it.
return rc

Original code would miss any folders with a space in them. Say ‘Sent Mail’ or ‘Follow Up’. This method seemed to work for me.

Also I added the following lines to the logout:

self.response = None
self.mailboxes = []

As I was iterating through multiple accounts I needed to empty those values between users.


crinus February 11, 2011

You got a really great tutorial here. And also taught me Python, by the way!

It’s nice doing code since I’ve been an avid coder in the past days, but
nothing inspired for long time. Email fetching and perhaps visualization
is one thing that interests me. With this tut, I got the Python basics as well.