The IMAP Protocol


 
Network Programming with Perl
By Lincoln  D.  Stein
Slots : 1
Table of Contents
Chapter  8.   POP, IMAP, and NNTP

    Content

The POP3 protocol was designed to handle the case of a user who spends most of his or her time working on a single machine. The mail client's job is to fetch the user's unread mail from time to time from the remote mailbox server. The user then reads the mail and possibly sorts it into several local mail folders.

Keeping track of mail becomes more complicated, however, when the user is moving around a lot: working on a desktop in the office, a laptop while traveling, and another desktop at home. In this case, the user wants to see the same set of mail files no matter where he or she happens to be working. The Internet Message Access Protocol (IMAP) satisfies these needs by managing multiple remote mail folders and transparently synchronizing them with local copies, providing the user with a consistent view of stored e-mail. IMAP clients also provide the user with the ability to work off-line, and with sophisticated server-side message search functions.

Unfortunately, the IMAP protocol is also rather complex and it does certain things that the simple request/response model of Net::POP3 can't easily handle. Among other things, IMAP servers send unsolicited messages to the client from time to time, for example to alert the client that new mail has arrived. No fewer than three Perl modules on CPAN deal with IMAP: Mail::IMAPClient, Net::IMAP, and Net::IMAP::Simple.

Mail::IMAPClient, written by David Kernen, provides the most functionality of the three, providing methods for issuing all of the IMAP commands. However, Mail::IMAPClient does not do such a good job at mapping the IMAP server's responses onto easily handled Perl objects. To use this module, you'll need RFC 2060 on hand and be prepared to parse the server responses yourself.

Net::IMAP, written by Kevin Johnson, does a better job at handling the server's responses, and provides a nifty callback interface that allows you to intercept and handle server events. Unfortunately, the module is in alpha stage and the interfaces are changing. Also, at the time this book was written, the module's documentation was incomplete.

Currently, the most usable interface to IMAP is Joao Fonseca's Net::IMAP::Simple, which provides access to the subset of IMAP that is most like POP3. In fact, Net::IMAP::Simple shares much of Net::POP3's method interface and is, to a large extent, plug compatible.

Like Net::POP3, you work with Net::IMAP::Simple by calling its new() , method to connect to an IMAP server host, authenticate with login() , list messages with list() and top() , and retrieve messages with get() . Unlike Net::POP3, Net::IMAP::Simple has no apop() method for authenticating without plaintext passwords. To make up for this deficiency, it has the ability to work with multiple remote mailboxes. Net::IMAP::Simple can list the user's mailboxes, create and delete them, and copy messages from one folder to another.

Summarizing an IMAP Mailbox

The pop_stats.pl program from Figure 8.1 summarizes the contents of a POP3 mailbox. We'll now enhance this program to summarize an IMAP mailbox. As an added feature, the new script, named imap_stats.pl , indicates whether a message has been read. You call it like pop_stats.pl , but with an additional optional command-line argument that indicates the name of the mailbox to summarize:

 %  pop_stats.pl lstein@localhoszt gd_bug_reports  lstein@localhost password: gd has 6 messages (2 new)   1 Honza Pazdziora       Re: ANNOUNCE: GD::Latin2 patch (fwd)    read   2 Gurusamy Sarathy      Re: patches for GD by Gurusamy Sarathy  read   3 Honza Pazdziora       Re: ANNOUNCE: GD::Latin2 patch (fwd)    read   4 Erik Bertelsen        GD-1.18, 2 minor typos                  read   5 Erik Bertelsen        GD fails om some GIF's                unread   6 Honza Pazdziora       GDlib version 1.3                     unread 

Figure 8.5 lists imap_stats.pl .

Figure 8.5. Summarize an IMAP mailbox

graphics/08fig05.gif

Lines 1 “5: Load modules We load Net::IMAP::Simple, Mail::Header, and the Prompt Util module used in earlier examples.

Lines 6 “9: Process command-line arguments We parse out the username and mailbox host from the first command-line argument, and recover the mailbox name from the second. If no mailbox name is provided, we default to INBOX , which is the default mailbox name on many UNIX systems. We then prompt for the user's password.

Lines 10 “14: Connect to remote host We call the Net::IMAP::Simple->new() , method to connect to the designated host, and then call login() to authenticate. If these steps are successful, we call the object's select() method to select the indicated mailbox. This call returns the total number of messages in the mailbox, or if the mailbox is empty or missing, undef . We fetch the number of the last message read by calling last() .

Lines 15 “24: List contents of the mailbox We loop through each of the messages from first to last. For each one, we fetch the header by calling top() , parse it into a Mail::Header object, and retrieve the Subject: and From: fields. We also call the IMAP object's seen() method to determine whether the message has been retrieved. We then print the message number, sender, subject line, and read status.

Lines 26 “32: clean_from() subroutine This is the same subroutine we saw in the earlier version of this program. It cleans up the sender addresses.

The Net::IMAP::Simple API

Although Net::IMAP::Simple is very similar to Net::POP3, there are some important differences. The most dramatic difference is that Net::IMAP::Simple does not inherit from Net::Cmd and, therefore, does not implement the message() or code() methods. Furthermore, Net::IMAP::Simple is not a subclass of IO::Socket and, therefore, cannot be treated like a filehandle.

The new() and login() methods are similar to Net::POP3:

$imap = Net::IMAP::Simple->new($host [,$opt1=>$val1, $opt2=>$val2 ])

The new() method constructs a new Net::IMAP::Simple object. The first argument is the name of the host, and is not optional (unlike the Net::POP3 equivalent). This is followed by a series of options that are passed directly to IO::Socket::INET.

If unsuccessful , new() returns undef and $! is set to some error code. Otherwise , it returns a Net::IMAP::Simple object connected to the server.

$messages = $imap->login($username,$password)

The login() method attempts to log into the server using the provided username and password. The username and password are required, also a departure from Net::POP3. If successful, the method returns the number of messages in the user's default mailbox, normally INBOX. Otherwise, login() returns undef .

Note that login() does not return 0E0 for a default mailbox that happens to be empty. The correct test for a successful login is to test for a defined return value.

Several functions provide access to mailboxes.

@mailboxes = $imap->mailboxes

The mailboxes() method returns a list of all the user's mailboxes.

$messages = $imap->select($mailbox)

The select() method selects a mailbox by name, making it current. If the mailbox exists, select() returns the number of messages it contains (0 for a mailbox that happens to be empty). If the mailbox does not exist, the method returns undef and the current mailbox is not changed.

$success = $imap->create_mailbox($mailbox)

$success = $imap->delete_mailbox($mailbox)

$success = $imap->rename_mailbox($old_name,$new_name)

The create_mailbox() , delete_mailbox() , and rename_mailbox() methods attempt to create, delete, and rename the named mailbox, respectively. They return true if successful, and false otherwise.

Once you have selected a mailbox, you can examine and retrieve its contents.

$last_msgnum = $imap->last

The last() method returns the highest number of the read messages in the current mailbox, just as Net::POP3 does. You can also get this information by calling the seen() method, as described below.

$arrayref = $imap->get($msgnum)

The get() method retrieves the message indicated by the provided message number from the current mailbox. The return value is a reference to an array containing the message lines.

$handle = $imap->getfh($msgnum)

This is similar to get() but the return value is a filehandle that can be read from in order to retrieve the indicated message. This method differs from the similarly named Net::POP3 method by returning a filehandle opened on a temporary file, rather than a tied filehandle. This means that the entire message is transferred from the remote server to the local machine behind the scenes before you can begin to ork with it.

$flag = $imap->delete($msgnum)

The delete() method marks the indicated message for deletion from the current mailbox. Marked messages are not removed until the quit() method is called. However, there is no reset() call to undo a deletion.

$arrayref = $imap->top($msgnum)

The top() method returns the header of the indicated message as a reference to an array of lines. This format is suitable for passing to the Mail::Header->new() method. There is no option for fetching a certain number of lines from the body text.

$hashref = $imap->list

$ size = $imap->list($msgnum)

The list() method returns information on the size of mailbox messages. Called without arguments, it returns a hash reference in which the keys are message IDs, and the values are the sizes of the messages, in bytes. Called with a message ID, the method returns the size of the indicated message, or if an invalid message number was provided, it returns undef .

$flag = $imap->seen($msgnum)

The seen() method returns true if the indicated message has been read (by calling the get() method), or false if it has not.

$success = $imap->copy($msgnum,$mailbox_destination)

The copy() method attempts to copy the indicated message from the current mailbox to the indicated destination mailbox. If successful, the method returns a true value and the indicated message is appended to the end of its destination. You may wish to call delete() to remove the message from its original mailbox.

When you are finished, the quit() method will clean up:

$imap->quit()

quit() takes no arguments. It deletes all marked messages and logs off.


   
Top


Network Programming with Perl
Network Programming with Perl
ISBN: 0201615711
EAN: 2147483647
Year: 2000
Pages: 173

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net