MailSneaker - Building a mail account watcher !

Last Update: 21.01.2007. By kerim in python | tutorial

We are going to buid a small program to check periodically for our mails. And to make it as unobtrusive as possible we let it settle in the taskbar, check for mails and (if there are new mails) it will tell us with a small popup or a change in the icon in the taskbar. We want to be able to open a browser then and have a look at the mails.. Perhaps we include a small preview of the mails … We will see.
To make it a little bit more powerfull we want several accounts to be checked. Configurable of course :)

So today we start with a small imap fetcher class.
Next follows a pop3 fetcher.
And we need a mailaccount class
Step number four will be the taskbaricon (different icons for “no new mail” and “new mail” and the periodical checks.
Last step should be a small gui for configuration (and one for mail preview ?)
The nice thing is that some of the program can be tried directly on idle and it wont take you longer than lets say 20 minutes to have a rudimentary client to log in and fetch your mails.

So lets start with the imap fetcher
… for imap more or less all we need is the imaplib. So of course we start with a :

import imaplib

Then of course we need a server url, an account name and a pass.

servername='imap.web.de'  
username= 'kmansour'  
password='now you didnt believe i wrote that down here did you ?'

Now comes the really complicated part .. we need to login to the server. Use these difficult calls.....

server = imaplib.IMAP4(servername)  
server.login(username,password)

Now that was hard wasn’t it ? ;-)
IDLE should give you something like:
(‘OK’, [‘LOGIN Completed: User logged in’])

We could do a lot of things now but for our purpose we ONLY want to see IF and perhaps what new mails we have gotten.
So we call:

server.search(None, '(UNSEEN UNDELETED)')

This SHOULD look in the INBOX for all mails that have not yet been flagged “read” or marked for deletion.
But when you call it you will get an error …
I dont know why yet but you must first call:

server.select(readonly=True) #(readonly is optional)

So again …

server.select(readonly=True)  
server.search(None, '(UNSEEN UNDELETED)')

And you should have some output like:
(‘OK’, [‘37’]) # for the select
(‘OK’, [‘’]) # for the search if you have NO new mails.

if you want to see the output for non-new mails just run:

server.search(None, '(UNDELETED)')

giving you for example:
(‘OK’, [‘1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27’, ‘28 29 30 31 32 33 34 35 36 37’])

So you get a list of MessageIds.
What you can do now is to run through all ids and get headers, bodies, attachments etc. .... but we dont really want that …
All we want for now is to see if there is a new mail or not so lets take a step back:

result=server.search(None, '(UNSEEN UNDELETED)')

result[1] should be a list....
And if it is not [‘’] then we should have new mail.

Thats not so difficult is it ?
So lets put that in a class !

import imaplib

class IMAPFetcher:  
        def __init__(self,sname, uname, passwd):  
        self.servername=sname  
        self.username=uname  
        self.password=passwd

    def fetch(self):  
        server = imaplib.IMAP4(self.servername)  
        server.login(self.username,self.password)  
        server.select(readonly=True) #(readonly is optional)  
        result=server.search(None, '(UNSEEN UNDELETED)')   
        if result[1]!=['']:  
            return result[1]

#--------------------testing---------------------  
servername='imap.web.de'  
username= 'kmansour'  
password='wont tell you here either'  
IF=IMAPFetcher(servername,username,password)  
print IF.fetch()

Bingo …