Troubleshooting Your POP Server with Perl

Many of us make the mistake of limiting our own vision. We put tools or people in boxes that are too confining. Even experienced Perl programmers sometimes believe, "Perl is great for text filters," or "Unix system administrators should use Perl to automate their work," without seeing that Perl can do much, much more. The fact is that Perl's virtues of expressiveness and concision apply to more than simple text manipulation or sysadmin automation.

Many of us make the mistake of limiting our own vision. We put tools or people in boxes that are too confining. Even experienced Perl programmers sometimes believe, “Perl is great for text filters,” or “Unix system administrators should use Perl to automate their work,” without seeing that Perl can do much, much more. The fact is that Perl’s virtues of expressiveness and concision apply to more than simple text manipulation or sysadmin automation.

Suppose you’re the administrator of an e-mail server. People look to you to solve their “I can’t get my messages!” complaints. You know the patterns: Users misremember their passwords, misconfigured firewalls block traffic, servers go haywire. Can Perl help?

Sure it can! Help desks are often trained to reproduce what the end user is doing. For the e-mail case, this might mean reconfiguring an e-mail client program like Netscape Communicator to duplicate what the end user is doing. Perl can help you do this much more quickly than by pointing-and-clicking, though. It’s also a lot easier to “glue” a little Perl utility together that will check this information for you.

Listing One: Complete Contents of pop-check Utility

1 #!/usr/bin/perl
2 use Net::POP3;
3 usage(0) if “-h” eq $ARGV[0] || “-help” eq $ARGV[0];
4 usage(1) if 2 != $#ARGV;
5 ($hostname, $account, $password) = @ARGV;
6 # Net::POP3->new () optionally takes a Timeout argument.
7 # This is handy for tracking down one class of problems.
8 $handle = Net::POP3->new($hostname) or die “Unable
to establish POP3 connection to $hostname.\n”;
9 defined($handle->login($account, $password)) or die
“Unable to authenticate ($account, $password)
at $hostname.\n”;
10 # I’ve never seen a POP3 server fail on the
$handle->list access.
11 # Still, it’s prudent to allow for the possibility.
12 $message_list = $handle->list or die “Unable to
retrieve list of available messages.\n”;
13 foreach $item (keys %$message_list) {
14 $header = $handle->top($item);
15 print @$header;
16 }
17 sub usage {
18 # This utility exposes PASSWORD in the process table
and on
19 #the wire.If you’re operating from an insecure host,
20 # you’ll want to compose an alternative user
interface to
21 # fortify defenses. Note that Net:POP3 includes an
22 # method.
23 print “Use this utility as ‘pop_check HOSTNAME
24 print ” or ‘pop_check -help’, to see this
25 exit($_[0]);
26 }

pop_check to the Rescue

The pop_check utility (Listing One) can be run from the command line to retrieve useful information immediately:


You can run this Perl script instead of reconfiguring your own e-mail client with the settings of your distressed user. And you don’t have to worry about resetting your original e-mail client configuration when you’re done, either. You can run pop_check from any platform that supports Perl, including Linux, Windows, and Macintosh. Rather than issuing an e-mail client’s muddy error messages (“Possible networking misconfiguration; consult your Network Administrator”), pop_ check will swiftly identify the most common e-mail problems. And this Perl utility does it in three dozen easily understood lines of source code.

You’ll see that lines 3 and 4 of Listing One present pop_check‘s user with a usage message. $#ARGV counts (one fewer than) the number of command-line arguments.

By line 6, pop_check will have exactly three command-line arguments. This compound assignment interprets them as the name of the POP3 server and a valid account-password combination on that server.

Graham Barr, Perl5.005 Source Maintainer, defined the libnet collection of Perl modules with object-oriented (OO) interfaces. While most introductions to Perl now explain at least the rudiments of its OO style, I particularly recommend the book Object-Oriented Perl by Damian Conway. Conway has appeared in Perl of Wisdom before; September 1999′s random-Randal generator depended crucially on Damian’s Parse::RecDescent module. His book, just published late this summer, is lucid, literate, and useful enough to be valuable for both beginners and experienced Perl programmers.

I’m careful to catch error conditions in lines 8 through 12. One of the best things a program can do is report comprehensibly on exceptions, faults, and confusions. Being a user is easy when everything’s working right; we particularly need the computer to do its part in generating feedback, though, when there’s a problem. This is especially true for pop_check. Most of the time I use pop_check because something is going wrong, and I need to track that down. Proper error messages are crucial.

In principle, the special variable $! includes more detailed diagnostic information, so it would be natural to write

die “Unable to establish POP3 connection to $hostname ($!).\n”;

or something similar. However, version 1.0606 does not yet set $! to anything interesting, so I ignore it.

Heed the defined() in line 9. As much as I like Christiansen and Torkington’s ground-breaking Perl Cookbook, their Net::POP3 example mishandles login()‘s return value. This is a common error. Often people write

somefunction() or die “message”

when they intend

defined(somefunction()) or die “message”

Finally, to confirm that the POP3 server is doing its job correctly, pop_check loops through the entire list of messages retained at the server and prints the header for each.

Going Farther

I mentioned above that much of pop_check‘s value lies in how it handles errors. This is not as unusual as you might first believe. The same Damian Conway has written a playful and profound Web page on the importance of error-handling. You can read it at http://www.cs.monash.edu.au/~damian/TPC/1999Coy.

Good Ideas Are Spoken in Many Languages

A program like pop_check surprises people who assume that, because typical e-mail clients are written in C or C++, all e-mail utilities should be written in C++.

In fact, bright people decoupled mechanism and function long before computers. One of my heroes was John Deere, whose work with a blade for a sawmill enabled the 1837 invention of his successful prairie plow. He saw how a technology recognized in manufacturing (the mechanism of the steel used in saw blades) benefited agricultural mechanization (a function important to him).

Perl is an apt subject for “hybridizing” creativity. The fact that end-user applications have been written in C++ or Visual Basic or other languages in the past does not limit you from considering Perl now. Perl has a particularly rich library for managing all the standard protocols with acronyms you’ve heard before: HTTP (Web service); SMTP, POP3, and IMAP4 (e-mail); FTP (file transfer); NNTP (Usenet newsgroups); SNMP (network management); LDAP (directory services); and dozens more. A few lines of Perl can give you useful results that would take much more time to write in C++ or other “third-generation” languages.

Moreover, because these protocols are standards, you’re free to mix them as you choose. This is the “On the Internet, no one knows you’re a dog” principle. It’s entirely legal to construct a whole application from pieces written in different languages. As long as they speak properly to each other, a Visual Basic client should be perfectly happy cooperating with a Perl-coded server. Moreover, you’re free to decide for yourself how to host such pieces, thanks to the work of such people as Robert Salita of Softworks Limited and Marc Woog of BMD Management Consulting AG. The former sells a portable version of Visual Basic, and the latter sponsors a Web page that describes how to build a Unix-like development environment (including Perl) under Windows.

Eyes Wide Open

Remember: Linux and Perl are general-purpose computing platforms. Both have been put into service on problems far afield from anything Linus Torvalds and Larry Wall originally planned. Practice opening your own eyes to new possibilities; you’re likely to find that Perl answers more questions than you realized.

Picking up the Net::POP3 module from CPAN

Before you can use the Net::POP3 module required by pop_ check, you might have to install it on your own machine. There are ways to automate this process so that it takes only a few seconds. Randal based last month’s column on the closely related Net::NNTP. When he wrote about it, he simply advised “use the CPAN installation tool to fetch and install” the modules you need. To guarantee your first use of Net::POP3 is successful, though, here is this process in detail:

1. Retrieve module from CPAN.

CPAN is the Comprehensive Perl Archive Network. It’s a treasure trove that holds millions of lines of valuable code.

To achieve our immediate goal, simply download into a temporary directory on your machine the contents of http://www.cpan.org/modules/by-module/Net/libnet-1.0606.tar.gz.

Eventually you’ll want to learn more about CPAN and its riches. The best way to do this is to read CPAN’s description of itself, at the Web site http://www.cpan.org/. Once you realize how you can multiply your effectiveness by re-using what others have made freely available, your next step should be to install the CPAN module http://www.cpan.org/modules/by-module/CPAN/CPAN-1.50.readme. This simplifies access to other modules. For now, though, we’ll build Net::POP3 by hand.

2. Unpack.

Under Linux or another Unix, this means

gunzip libnet-1.0606.tar.gz
tar xf libnet-1.0606.tar
cd libnet-1.0606

It’s also possible to install Net under Windows, MacOS, or other operating systems Perl supports, with just a bit more complexity. Cross-platform worries are a subject for a different issue, of course.

3. Generate.

perl Makefile.PL
make install

To install, you’ll generally need root permissions. If this is a problem, you can read the distributed installation directions for information on how to configure the generation so that super-user privileges are not necessary.

Cameron Laird is vice president of Phaseit, Inc. He can be reached at claird@neosoft.com.

Comments are closed.