Software Development

Code an application to read POP3 mailboxes with Perl

This document explores some of the specific Perl capabilities developers can use to create a simple POP3 mail application.

E-mail clients like Microsoft Outlook and Mozilla Thunderbird make it incredibly simple to get to your e-mail – most of the time, all you need to do is click a toolbar button and the software does the hard work of communicating with your mail server, authenticating your password, and retrieving your e-mail.

Behind this deceptively simple interface, though, is an immense amount of software programming. And, if you're a software developer, you might one day find yourself in the unenviable position of having to replicate this programming in your own application.

Don't worry too much about it, though, because if you're using Perl, you can take advantage of a useful little CPAN module called Net::POP3, which handles most of the drudge work for you. This module exposes a simple and powerful API to POP3 server interaction, providing pre-built methods for server authentication, message listing and retrieval, message deletion, and graceful session closure – in short, everything you need to satisfy basic user needs.


Note: The code snippets in Listing A-C are available in a text file included with the downloadable zip file.


This document explores some of Net::POP3's capabilities by using it to develop a simple POP3 mail application. To begin with, download and install the module (if you don't already have it) by running the following commands at your Perl prompt:

perl> perl -MCPAN -e "install Net::POP3"

Begin by creating the following Perl script (Listing A):

Listing A


#!/bin/perl

# import package
use Net::POP3;

# ask user for critical variables
print "Mail host: ";
$host = <STDIN>;
chomp($host);

print "\n";
print "Mailbox username: ";
$user = <STDIN>;
chomp($user);

print "\n";
print "Mailbox password: ";
$pass = <STDIN>;
chomp($pass);

# initiate connection
# default timeout = 120 sec
$conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");

# login
$numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");

# display number of messages
if ($numMsg > 0) {
    print "Mailbox has $numMsg message(s).\n";
} else {
    print "Mailbox is empty.\n";
}

# close connection
$conn->quit();

This script asks the user to input three items: the mail server host name, the POP3 user name and the corresponding password. Once these values have been entered, a new Net::POP3 object is created and the object's login() method is used to open a connection to the host and validate the supplied credentials. Assuming the credentials are accepted by the server, the login() method returns the number of messages in the mailbox (or 0 if none exist).

Here's an example of it in action:

Mail host: pop.mailbox.com
Mailbox username: jane
Mailbox password: secret

Mailbox has 77 message(s).

Of course, just knowing the number of messages is not all that useful – ideally, you'd also like to see what they contain. Net::POP3 lets you do this via its top() method, which scans the first X lines of a message and returns a reference to an array containing the retrieved data. Here's an example, (Listing B) which retrieves the first 20 lines of all messages in the mailbox:

Listing B


#!/bin/perl

# import package
use Net::POP3;

# ask user for critical variables
print "Mail host: ";
$host = <STDIN>;
chomp($host);

print "\n";
print "Mailbox username: ";
$user = <STDIN>;
chomp($user);

print "\n";
print "Mailbox password: ";
$pass = <STDIN>;
chomp($pass);

# initiate connection
# default timeout = 120 sec
$conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");

# login
$numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");

# get message numbers
# iterate over list and print first 20 lines of each
if ($numMsg > 0) {
    $msgList = $conn->list();
    foreach $msg (keys(%$msgList)) {
        $ref = $conn->top($msg, 20);
        print @$ref;
        print "\n\n";
    }
} else {
    print "Mailbox is empty.\n";   
}

# close connection
$conn->quit();

You can retrieve the complete message by using the get() method instead of the top() method.

If you'd prefer, you can pass the server parameters to the program on the command line through the Getopt::Long module. Here's a variant of the code above, which demonstrates this module (Listing C):

Listing C


#!/bin/perl

# import packages
use Net::POP3;
use Getopt::Long;

# read command line options
# display usage message in case of error
GetOptions ('h|host=s' => \$host,
            'u|user=s' => \$user,
            'p|pass=s' => \$pass) or die("Input error. Try calling me with: -h <host> -u <username> -p <password>");

# initiate connection
# default timeout = 120 sec
$conn = Net::POP3->new($host) or die("ERROR: Unable to connect.\n");

# login
$numMsg = $conn->login($user, $pass) or die("ERROR: Unable to login.\n");

# get message numbers
# iterate over list and print first 20 lines of each
if ($numMsg > 0) {
    $msgList = $conn->list();
    foreach $msg (keys(%$msgList)) {
        $ref = $conn->top($msg, 20);
        print @$ref;
        print "\n\n";
    }
} else {
    print "Mailbox is empty.\n";   
}

# close connection
$conn->quit();

These script templates will give you some idea of how you can integrate Net::POP3 into applications that require e-mail transactions. Try them out for yourself, and happy coding!

0 comments

Editor's Picks