IMAPs Unique Message IDs

Complaints about imaplib's user-friendliness aside, you might have problems writing IMAP scripts if you assume that the message numbers don't change over time. If another IMAP client deletes messages from a mailbox while this script is running against it (suppose you have your mail client running, and you use it to delete some spam while this script is running), the message numbers will be out of sync from that point on.

The IMAP-based SubjectLister class minimizes this risk by getting the subject of every message in one operation, immediately after selecting the mailbox:

self.fetch('1:%d' % numberOfMessages, '(BODY[HEADER.FIELDS (SUBJECT)])')

If there are 10 messages in the inbox, the first argument to fetch will be "1:10". This is a slice of the mailbox, similar to a slice of a Python list, which returns all of the messages: message 1 through message 10 (IMAP and POP3 messages are numbered starting from 1).

Getting the data you need as soon as you connect to the server minimizes the risk that you'll pass a no-longer-valid message number onto the server, but you can't always do that. You may write a script that deletes a mailbox's messages, or that files them in a second mailbox. After you change a mailbox, you may not be able to trust the message numbers you originally got.

Try It Out Fetching a Message by Unique ID

To help you avoid this problem, IMAP keeps a unique ID (UID) for every message under its control. You can fetch the unique IDs from the server and use them in subsequent calls using imaplib's uid method. Unfortunately, this brings you even closer to the details of the IMAP protocol. The IMAP4 class defines a separate method for each IMAP command (e.g. lMAP4.fetch, lMAP4.search, etc.), but when you're dealing with IDs, you can't use those methods. You can use only the lMAP4.uid method, and you must pass the IMAP command you want as the first argument. For instance, instead of calling IMAP4.fetch([arguments]), you must call IMAP4.uid('FETCH', [arguments]).

>>> import imaplib >>> import email

>>> imap = imaplib.IMAP4('imap.example.com') >>> imap.login('[username]', '[password]') ('OK', ['Logged in.']) >>> imap.select('Inbox')[1][0]

>>> #Get the unique IDs for the messages in this folder. ... uids = imap.uid('SEARCH', 'ALL') >>> print uids

>>> #Get the first message. ... uids = uids[1][0].split(' ')

>>> messageText = imap.uid('FETCH', uids[0], "(RFC822)")[1][0][1] >>> message = email.message_from_string(messageText) >>> print message['Subject'] This is a test message #1

Was this article helpful?

0 0

Post a comment