gpinzone has asked for the wisdom of the Perl Monks concerning the following question:

I had to write a program to read emails through POP3. Based on the searches I've made and the documentation I've read, it was relatively easy to do using Mail::POP3Client. There are enough examples to get a basic program that will retrieve emails written very quickly. However, I was surprised that I couldn't easily find a more detailed program. For example, I soon learned (the hard way) about message encodings (Base64 and Quoted-Printable). I found posts here that directed people to MIME::QuotedPrint and MIME::Base64 libraries for decoding the email bodies. It was easy enough to check the header for encoding entries:

# Process header for (split /^/, $header) { if ( /^From:\s+<(.*?)>/i ) { $from = $1 }; if ( /^Subject:\s+(.*)/i ) { $subject = $1 }; } # Decode body if encoded if ( $header =~ /Content-Transfer-Encoding:\s+base64/is ) { $body = decode_base64($body); } elsif ( $header =~ /Content-Transfer-Encoding:\s+quoted-printable/is ) { $body = decode_qp($body); }

But I was surprised this was a "manual" process left up to the user. Then I discovered some characters in the body were wrong. The emails are utf8 encoded and seemed to be readable 99.9% of the time, but every so often, I'd see a character get messed up. Things like a single-right-quote wouldn't convert properly. I searched again and found Encoding::FixLatin which did the trick. So yes, I got it all working, but it seemed very inelegant.

I happened to stumble on a bit of code while looking for more information on Perl and utf8 that used Email::MIME to process emails. Most examples using Email::MIME I've seen are for encoding (i.e., sending) emails. I'm surprised at the lack of search results for email reading examples using Email::MIME.

I don't like to ask for help for things that may be obvious by Googling. However, at this point I just want some verification and suggestions for improvement. I'm posting up a sample Perl script that will read email from a SSL POP3 connection. What I'd like to know is, am I doing it "right?" Is this the best way to accomplish this?

#!/usr/bin/perl use Modern::Perl; use Mail::POP3Client; use Email::MIME; use IO::Socket::SSL; use Encode; # Set output to UTF8 use utf8; binmode(STDOUT, ":utf8"); # Retrieve emails through POP3 my $pop_user = '********'; my $pop_pass = '********'; my $pop_host = 'mail.********.com'; # Connect to POP3 sever # Manually create SSL connection since we can't # set SSL_verify_mode in Mail::POP3Client my $socket = IO::Socket::SSL->new( PeerAddr => $pop_host, PeerPort => 995, SSL_verify_mode => SSL_VERIFY_NONE, Proto => 'tcp') || die "N +o socket!"; my $pop = Mail::POP3Client->new(); $pop->User($pop_user); $pop->Pass($pop_pass); $pop->Socket($socket); $pop->Connect() or die "Unable to connect to POP3 server: ".$pop->Message()."\n"; # Count number of items in mailbox my $mailcount = $pop->Count(); # Process each email individually for (my $i = 1; $i <= $mailcount ; $i++) { my $header = $pop->Head($i); # Gets the email header #my $uni = $pop->Uidl($i); # Gets the unique id #my $body = $pop->Body($i); # Gets the email body my $mail = $pop->HeadAndBody($i); my $parsed = Email::MIME->new($mail); my $from = encode('utf8', $parsed->header('From')); my $subject = encode('utf8', $parsed->header('Subject')); my $body = $parsed->body_str; say "$header"; say "$body\n"; } # END for loop # Close POP connection $pop->Close();

Replies are listed 'Best First'.
Re: Mail::POP3Client basic program
by blue_cowdawg (Monsignor) on Jan 29, 2013 at 15:36 UTC
        However, I was surprised that I couldn't easily find a more detailed program.

    Were you expecting a full blown MUA implementation perhaps?

    It is usually assumed by CPAN authors that you know what you are after and have some idea how to fill in the blanks.


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
      Sure. I expected to find at least one fully implemented email script. It's not a matter of whether or not I could reinvent the wheel. It's a matter of how hasn't this been done (and posted) already a thousand times? What's also surprising is seeing responses to use MIME::QuotedPrint and MIME::Base64 when Email::MIME does it all and does it more elegantly and completely.
            I expected to find at least one fully implemented email script. It's not a matter of whether or not I could reinvent the wheel.

        Rare is the day that I've seen full blown implementations of things as a program example in the documentation for a module. There's a very good reason for that. Where I work we have an email processing script that reads incoming emails from a Qmail queue and performs autonomous processing of those emails. It handles every concievable popular MIME attachment you can think of. The code consists of around 6000 lines of code scattered around a main script and several modules. I'd hate to download a CPAN module that had that large of an example embedded in it.

        Not only that a piece of code given as an example of code to be written by the module is meant to provide an example of that module only. Not the half a dozen or more that you need for a full blown application.

        Based on your comments I'd say you started off with a poor understanding of the scope your project. That's a first step. "I want to build a POP client" is not good scope definition.


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg