How can I check the number of unread Gmail message in my inbox with a short Python script? Bonus points for retrieving the password from a file.
8 Answers
import imaplib
obj = imaplib.IMAP4_SSL('imap.gmail.com','993')
obj.login('username','password')
obj.select()
obj.search(None,'UnSeen')

- 4,519
- 5
- 33
- 44
-
7I really like this solution. Generally clean with only one import. To get the number you'd just: len(obj.search(None, 'UnSeen')[1][0].split()) – Steven Hepting Oct 31 '10 at 03:27
-
can I get message bodies and subjects with this solution? – DataGreed Jan 07 '13 at 21:41
-
1@DataGreed: With the search, you get only the mail id's, but you can then use that with "obj.fetch(..." to get the mails you want. See this link for example of how to do that: http://yuji.wordpress.com/2011/06/22/python-imaplib-imap-example-with-gmail/ – Samuel Lampa Feb 09 '13 at 16:59
-
Using this I got notification that someone just used my password to try to log in using unsecure app, with link to this doc: https://support.google.com/accounts/answer/6010255?p=lsa_blocked&hl=en&visit_id=636846249310990834-3121226013&rd=1 – Bunyk Feb 01 '19 at 13:37
-
For those who are curious about connecting to gmail using imaplib, google will periodically disable 3rd party access and you will have to manually enable it. Better to create an app and use the gmail api instead. – nurettin Nov 19 '20 at 09:06
-
Since June 2022 IMAP access no longer works. – Ruslan Jun 12 '22 at 17:43
I advise you to use Gmail atom feed
It is as simple as this:
import urllib
url = 'https://mail.google.com/mail/feed/atom/'
opener = urllib.FancyURLopener()
f = opener.open(url)
feed = f.read()
You can then use the feed parse function in this nice article: Check Gmail the pythonic way

- 1,231
- 15
- 31

- 111,714
- 37
- 173
- 152
-
3What's so bad about IMAP? Note that this snippet is not complete, despite the "simple as this". – Matthew Flaschen Jun 05 '09 at 02:41
-
Also note that this solution will prompt the user for username, password on the TTY. However, you can subclass the opener to handle this. – Matthew Flaschen Jun 05 '09 at 03:08
-
3It always returns unauthorized for me File "/opt/python2.7/lib/python2.7/urllib.py", line 379, in http_error_default raise IOError, ('http error', errcode, errmsg, headers) IOError: ('http error', 401, 'Unauthorized',
) – gennad May 01 '11 at 07:55
Well, I'm going to go ahead and spell out an imaplib solution as Cletus suggested. I don't see why people feel the need to use gmail.py or Atom for this. This kind of thing is what IMAP was designed for. Gmail.py is particularly egregious as it actually parses Gmail's HTML. That may be necessary for some things, but not to get a message count!
import imaplib, re
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login(username, password)
unreadCount = re.search("UNSEEN (\d+)", conn.status("INBOX", "(UNSEEN)")[1][0]).group(1)
Pre-compiling the regex may improve performance slightly.

- 278,309
- 50
- 514
- 539
-
1While I happen to agree IMAP is the way to go here, there are some portability issues that could occur. Since the other methods are using HTTP connections, they could conceivably work when IMAP wouldn't (in restrictive environments like Google App Engine or on networks where non-HTTP traffic is restricted). – Tom Jun 06 '09 at 23:23
-
9Tom, that's true. But the OP didn't say they were dealing with those limitations, so we should not invent them prematurely. – Matthew Flaschen Jun 08 '09 at 01:47
For a complete implementation of reading the value from the atom feed:
import urllib2
import base64
from xml.dom.minidom import parse
def gmail_unread_count(user, password):
"""
Takes a Gmail user name and password and returns the unread
messages count as an integer.
"""
# Build the authentication string
b64auth = base64.encodestring("%s:%s" % (user, password))
auth = "Basic " + b64auth
# Build the request
req = urllib2.Request("https://mail.google.com/mail/feed/atom/")
req.add_header("Authorization", auth)
handle = urllib2.urlopen(req)
# Build an XML dom tree of the feed
dom = parse(handle)
handle.close()
# Get the "fullcount" xml object
count_obj = dom.getElementsByTagName("fullcount")[0]
# get its text and convert it to an integer
return int(count_obj.firstChild.wholeText)

- 79
- 1
- 2
Well it isn't a code snippet but I imagine using imaplib and the Gmail IMAP instructions get you most of the way there.

- 616,129
- 168
- 910
- 942
Once you are logged in (do this manually or with gmail.py) you should use the feed.
It is located here: http://mail.google.com/mail/feed/atom
It is the way Google does it. Here is a link to their js chrome extension: http://dev.chromium.org/developers/design-documents/extensions/samples/gmail.zip
You will then be able to parse xml that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<title>Gmail - Inbox for yourmail@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>142</fullcount>

- 45,913
- 27
- 138
- 182
I didn't like the existing solutions so I decided to make a sister library for my email sender called Red Box.
It has a pre-configured gmail
instance:
from redbox import gmail
# Configure Gmail
gmail.username = "example@gmail.com"
gmail.password = "<PASSWORD>"
# Select inbox folder
inbox = gmail.inbox
# Get unread emails
msgs_unread = inbox.search(seen=False)
# Print unread count
print(len(msgs_unread))
Red Box fetches the email contents only when needed. The above does not do that as we didn't access the contents of these messages. You can also easily access various parts of the messages if you need.
I also wrote how to configure Gmail's app password here:
To install:
pip install redbox
Links:

- 2,426
- 1
- 18
- 34
Use Gmail.py
file = open("filename","r")
usr = file.readline()
pwd = file.readline()
gmail = GmailClient()
gmail.login(usr, pwd)
unreadMail = gmail.get_inbox_conversations(is_unread=True)
print unreadMail
Gets login information from a text file assuming the login name and password are on separate lines.

- 3,306
- 24
- 23
-
4I checked the module source, what it does it open gmail in html mode and parse the page. This is bad! http://www.holovaty.com/code/gmail.py – Nadia Alramli Jun 04 '09 at 23:20
-
readline includes a trailing newline, which you don't want here. – Matthew Flaschen Jun 04 '09 at 23:24
-
1Nadia is right. This will waste significant time and bandwidth. – Matthew Flaschen Jun 05 '09 at 03:05
-