Reading E-mail Via the Web
Now that we have seen how Net::POP3 allows us to retrieve and read mail from a POP server, let's look at how we can integrate it into a CGI program. First, an HTML form is needed as a way to enter a user name and password. Here is a simple one:
<HTML> <Head> <Title>Read your mail!</Title> </Head> <Body> <H1>Read your mail!</H1> <P>Enter your user name, password, and POP server.</P> <Form method="POST" action="/cgi-bin/print-mail.pl"> <P>POP server: <input type="text" name="mailserver"></P> <P>Username: <input type="text" name="username"></P> <P>Password: <input type="password" name="password"></P> <P><input type="submit" value="Show me my mail!"></P> </Form> </Body> </HTML>
The above form sends three parameters to our CGI program—the name of the POP server from which to download the mail, the user name and the password. If you are concerned about the password being sent in the clear, you might want to put the form and CGI program behind a server running SSL, the secure sockets layer. You might also want to investigate POP3's APOP login method, which hides the password somewhat.
The program for reading mail is fairly simple; see Listing 1 in the archive file, ftp://ftp.linuxjournal.com/pub/lj/listings/issue61/3359.tgz. The code starts by creating an instance of CGI, providing an object-oriented interface to the CGI protocol. Then an appropriate MIME header is sent to the user's browser, indicating the response will be in HTML-formatted text. Next, the three pieces of information necessary for retrieving the user's mail are grabbed: the name of the POP server, the user name and the password.
Once that information is retrieved, we try to connect to the POP server and log in. Normally, invoking die is a bad idea in a CGI program, since it results in a difficult-to-understand message appearing on the user's screen. However, since we ported CGI::Carp and specified fatalsToBrowser, any invocations of die will send a description of the error message to the browser as well as to the web server's error log. This can be an invaluable tool when debugging, even if your final production code requires you to hide potential error messages.
Once the number of messages waiting on the POP server is known, we can retrieve them with a simple loop:
foreach my $index (1 .. $num_messages)
{
print "<H2>Message $index</H2>\n";
my $message_ref = $pop->get($index);
print "<pre>\n", @$message_ref, "</pre><HR>\n";
}
We enclose the mail within <pre> and </pre> tags, since most e-mail depends on fixed-width fonts and formatting.
You may be surprised such a simple program can be used to read your mail, but it does and should work on any system with any web browser. It can be used to quickly check if any new mail has arrived, without affecting your ability to download and read messages with your usual e-mail program.
As is often the case with new programs, our first stab was functional but is missing some useful features. For instance, most users do not need to see all of the headers that come with a message. Typically, they want to see only the “From”, “To”, “Subject”, “Cc” and “Date” headers.
Perl makes it a snap to remove unwanted headers by using regular expressions. Headers can be thought of as a name, value pair separated by a colon. On the left side of the colon is the header name, which can consist of any alphanumeric character or a hyphen. On the right side of the colon is the header's value, which can consist of almost any character.
One consideration is the possibility that a header will be spread across multiple lines. That is, the two lines
Subject: This is a subject header that continues onto a second line
should all be considered part of the “Subject” header, since the second line begins with one or more white-space characters.
This problem is solved by creating a hash, %KEEP, in which the keys name the headers to keep. For example:
my %KEEP = ("To" => 1,
"From" => 1,
"Subject" => 1,
"Date" => 1);
The code then checks if a header is to be kept by checking the value of $KEEP{$header_name}, where $header_name contains the value of the header to check.
Before anything can be done to the headers, they must be put into a scalar separate from the message body. Do that with split:
my ($headers, $body) = split "\n \n", $contents, 2;
Notice split has three arguments, telling Perl to split $contents into a maximum of two elements. If the 2 were omitted, $body would contain only the first paragraph of the message, rather than the entire text.
Once the message headers are stored in $headers, it can be split back into an array, and the code can then iterate through the array elements. Each element of @headers is a single header line, which might mark the beginning of a new header or the continuation of an existing one. If this is a new header and its name is in %KEEP, the header is written to the user's browser. If the header's name is not in %KEEP, it is ignored and the program goes on to the next line.
This does not solve the issue of multi-line headers. This is handled by assuming that every line in @headers will begin with either a header (e.g., Received: or X-Mailer:) or with white space. If the pattern at the beginning of the line matches a header value, the program checks %KEEP and if found, prints the line. If the pattern fails to match a header value, it is assumed to be white space, and the line is printed only if the previous line was printed.
Here is some basic code to print the headers:
my @headers = split "\n", $headers;
my $previous = "";
foreach my $line (@headers)
{
if ($line =~ m/^([\w-]+):/i)
{
$previous = $1;
}
print $line, "\n" if $KEEP{$previous};
}
This code is contained in Listing 2, better-print-mail.pl, in the archive file. This is an improved version of our original bare-bones program, incorporating this and other changes.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- I once had a better way I
4 hours 38 min ago - Not only you I too assumed
4 hours 55 min ago - another very interesting
6 hours 48 min ago - Reply to comment | Linux Journal
8 hours 42 min ago - Reply to comment | Linux Journal
15 hours 36 min ago - Reply to comment | Linux Journal
15 hours 52 min ago - Favorite (and easily brute-forced) pw's
17 hours 43 min ago - Have you tried Boxen? It's a
23 hours 35 min ago - seo services in india
1 day 4 hours ago - For KDE install kio-mtp
1 day 4 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




Comments
extracting the headers with
I am trying to extract the subject line from emails and your article is helping me.
What does the "w-" do in the regular expression "m/^([w-]+):/i)" ?
It's just above the heading "Handling HTML".
Is it supposed to match a character class consisting of "w" and "-" ? I would think something like "s" would be used to match leading whitespace.
Thanks