Reading Mail with POP3 (Perl Cookbook, 2nd Edition)

## 18.5. Reading Mail with POP3

### 18.5.1. Problem

You want to fetch mail from a POP3 server. This lets you write a program to summarize your unread mail, move it from a remote server to a local mailbox, or toggle between Internet and local mail systems.

### 18.5.2. Solution

Use the Net::POP3 module:

>     $pop = Net::POP3->new($mail_server)
>         or die "Can't open connection to $mail_server : $!\n";
>     defined ($pop->login($username, $password))
>         or die "Can't authenticate: $!\n";
>     $messages = $pop->list
>         or die "Can't get list of undeleted messages: $!\n";
>     foreach $msgid (keys %$messages) {
>         $message = $pop->get($msgid);
>         unless (defined $message) {
>             warn "Couldn't fetch $msgid from server: $!\n";
>             next;
>         }
>         # $message is a reference to an array of lines
>         $pop->delete($msgid);
>     }

### 18.5.3. Discussion

Traditionally, mail has been a three-party system: the MTA (Mail Transport Agent, a system program like sendmail) delivers mail to the spool, where it is read by the MUA (Mail User Agent, a program like mail). This dates from the days of big servers holding mail and users reading it through dumb terminals. As PCs and networks entered the picture, the need arose for MUAs like Pine to run on different machines than the one housing the spool. The Post Office Protocol (POP) implements efficient message listing, reading, and deleting over a TCP/IP session.

The Net::POP3 module is a POP client. That is, it lets your Perl program act as an MUA. The first step in using Net::POP3 is to create a new Net::POP3 object. Pass `new` the name of the POP3 server:

>     $pop = Net::POP3->new( "pop.myisp.com" )
>         or die "Can't connect to pop.myisp.com: $!\n";

All Net::POP3 functions return `undef` or the empty list upon error, depending on the calling context. If an error occurs, the fickle `$!` variable just might contain a meaningful error message—but also might not.

You may optionally pass further arguments to `new` using named-parameter pairs. The "Timeout" parameter specifies a timeout value in seconds for all network operations.

>     $pop = Net::POP3->new( "pop.myisp.com",
>                            Timeout => 30 )
>         or die "Can't connect to pop.myisp.com : $!\n";

Authenticate yourself to the POP3 server with the `login` method. It takes two arguments, username and password, but both are optional. If the username is omitted, the current username is used. If the password is omitted, Net::POP3 tries to use Net::Netrc to find a password:

>     defined ($pop->login("gnat", "S33kr1T Pa55w0rD"))
>         or die "Hey, my username and password didn't work!\n";

>     defined ($pop->login( "midget" ))           # use Net::Netrc to find password
>         or die "Authentication failed.\n";

>     defined ($pop->login( ))                     # current username and Net::Netrc
>         or die "Authentication failed.  Miserably.\n";

The `login` method sends the password in plain text across the network. This is virtually always undesirable, so you can use the `apop` method instead. It works exactly like `login`, except that it encrypts the password:

>     $pop->apop( $username, $password )
>         or die "Couldn't authenticate: $!\n";

Once authenticated, you may then access the spool with `list`, `get`, and `delete`. The `list` method gives you a list of undeleted messages in the spool. It returns a hash where each key is a message number and each value the size in bytes of the corresponding message:

>     %undeleted = $pop->list( );
>     foreach $msgnum (keys %undeleted) {
>         print "Message $msgnum is $undeleted{$msgnum} bytes long.\n";
>     }

To retrieve a message, call `get` with the message number. It returns a reference to an array of lines in the message:

>     print "Retrieving $msgnum : ";
>     $message = $pop->get($msgnum);
>     if ($message) {
>         # succeeded
>         print "\n";
>         print @$message;                # print the message
>     } else {
>             # failed
>         print "failed ($!)\n";
>     }

The `delete` method marks a message as deleted. When you call `quit` to terminate your POP3 session, the messages marked as deleted are removed from the mailbox. The `reset` method undoes any `delete` calls made during the session. If the session is terminated by the Net::POP3 object being destroyed (e.g., the only reference to the object went out of scope), `reset` is called automatically.

You have probably noticed there's no way to send mail. POP3 only supports reading and deleting existing messages. To send new ones, you still have to use programs like mail or sendmail, or do `SMTP`. In other words, you still need Recipe 18.3.

The task attempted by POP3—connecting mail clients and mail servers—is also attempted by the IMAP protocol. IMAP has more features and is more typically seen on very large sites.

### 18.5.4. See Also

The documentation for the Net::POP3 module; RFC 1734, POP3 AUTHentication command; RFC 1957, Some Observations on Implementations of the Post Office Protocol

Copyright © 2003 O'Reilly & Associates. All rights reserved.