09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

CHAPTER 15 ■ IMAP<br />

Like many Internet protocols (HTTP comes immediately to mind), IMAP internally uses CR-LF<br />

('\r\n' in <strong>Python</strong>) to designate the end <strong>of</strong> a line. Some IMAP servers will have problems if you upload a<br />

message that uses any other character for the end <strong>of</strong> a line. Therefore, you must always be careful to<br />

have the correct line endings when you translate uploaded messages. This problem is more common<br />

than you might expect, since most local mailbox formats use only '\n' for the end <strong>of</strong> each line.<br />

However, you must also be cautious in how carefully you change the line endings, because some<br />

messages may use '\r\n' somewhere inside despite using only '\n' for the first few dozen lines, and<br />

IMAP clients have been known to fail if a message uses both different line endings! The solution is a<br />

simple one, thanks to <strong>Python</strong>’s powerful splitlines() string method that recognizes all three possible<br />

line endings; simply call the function on your message and then re-join the lines with the standard line<br />

ending:<br />

>>> 'one\rtwo\nthree\r\nfour'.splitlines()<br />

['one', 'two', 'three', 'four']<br />

>>> '\r\n'.join('one\rtwo\nthree\r\nfour'.splitlines())<br />

'one\r\ntwo\r\nthree\r\nfour'<br />

The actual act <strong>of</strong> appending a message, once you have the line endings correct, is to call the<br />

append() method on your IMAP client:<br />

c.append('INBOX', my_message)<br />

You can also supply a list <strong>of</strong> flags as a keyword argument, as well as a msg_time to be used as its<br />

arrival time by passing a normal <strong>Python</strong> datetime object.<br />

Asynchrony<br />

Finally, a major admission needs be made about this chapter’s approach toward IMAP: even though we<br />

have described IMAP as though the protocol were synchronous, it in fact supports clients that want to<br />

send dozens <strong>of</strong> requests down the socket to the server and then receive the answers back in whatever<br />

order the server can most efficiently fetch the mail from disk and respond.<br />

The IMAPClient library hides this protocol flexibility by always sending one request, waiting for the<br />

response, and then returning that value. But other libraries—and in particular the IMAP capabilities<br />

provided inside Twisted <strong>Python</strong>—let you take advantage <strong>of</strong> its asynchronicity.<br />

But for most <strong>Python</strong> programmers needing to script mailbox interactions, the synchronous<br />

approach taken in this chapter should work just fine.<br />

Summary<br />

IMAP is a robust protocol for accessing e-mail messages stored on a remote server. Many IMAP libraries<br />

exist for <strong>Python</strong>; imaplib is built into the Standard Library, but requires you to do all sorts <strong>of</strong> low-level<br />

response parsing by yourself. A far better choice is IMAPClient by Menno Smits, which you can install<br />

from the <strong>Python</strong> Package Index.<br />

On an IMAP server, your e-mail messages are grouped into folders, some <strong>of</strong> which will come predefined<br />

by your particular IMAP provider and some <strong>of</strong> which you can create yourself. An IMAP client can<br />

create folders, delete folders, insert new messages into a folder, and move existing messages between<br />

folders.<br />

Once a folder has been selected, which is the IMAP rough equivalent <strong>of</strong> a “change directory”<br />

command on a filesystem, messages can be listed and fetched very flexibly. Instead <strong>of</strong> having to<br />

download every message in its entirety—though, <strong>of</strong> course, that is an option—the client can ask for<br />

particular information from a message, like a few headers and its message structure, in order to build a<br />

261

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!