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

I have been trying to write a small email parsing filter. Here is the how it should work:
  1. server recieves email and pipes it to the email filter
  2. the filter strips the to, from, subject and body from the email.
  3. if the body is of type mime, it is decoded and any attachments can be saved to a local directory.
  4. a response email is generated notifying the sender it their email was received and then the original email is simple sent to /dev/null. no need to save it locally.
I have been attempting to use Email::Filter... so far, I have it able to receive the email, send a response using Mail::Sendmail and then dump the message to /dev/null. So far so good. Here is my problem, i can't get it to write to a log file and i have been trying to figure out how to parse the body and save files locally. (for example, an jpeg image). Here is my lil code so far:
use Email::Filter; use Mail::Sendmail; BEGIN { $mail = Email::Filter->new(); $mail->exit(0); } my $to = $mail->to; my $from = $mail->from; my $subject = $mail->subject; my $body = $mail->body; open (LOG, qq|>>MAIL.txt|); print LOG qq|TO => $to\n|; print LOG qq|FROM => $from\n|; print LOG qq|SUBJECT => $subject\n|; print LOG qq|BODY => $body\n|; close (LOG); END { my %hash = ( to => $from , from => 'foo@bar.com' , subject => 'Mail recieved' , body => 'Your message has been received' , smtp => 'foobar.com' ); open(ERROR, qq|>>ERROR.txt|); sendmail(%hash) or print ERROR qq|Couldn't send mail... $!\n|; #uncomment following lines for debugging only print ERROR qq|$Mail::Sendmail::error \n|; print ERROR qq|\$Mail::Sendmail::log says:\n$Mail::Sendmail::log\n +|; close (ERROR); $mail->exit(1); $mail->accept('/dev/null'); }
any suggestions?

Replies are listed 'Best First'.
Re: Email modules
by NetWallah (Canon) on Aug 24, 2004 at 00:33 UTC
    Try the Mail::Box modules.

    There is a bit of a learning curve, but these are the best-designed and most comprehensive set of mail modules I have found.

    sample code I'm working on ...

    use strict; use Mail::Box::Manager; use POSIX qw(strftime); # Dont REALLY need this use Date::Parse qw( str2time ); use Date::Manip; my $MailboxManager = Mail::Box::Manager->new; ReadMail('Mailbox-name' ,'PASSWORD' ,'Server_Name.domain.com'); ############################################################# sub ReadMail{ my ($UserName, $Password, $Server) = @_; # User should included domain, and Mailbox info, as required by serv +er. my $POP3InboxFolder = $MailboxManager->open(type => 'pop3' , folder +=>'/' , username => $UserName, password => $Password ,server_name => $Server ,access => 'r', ,fix_header_errors => 1, fixHeaderErrors=> 1) or die "Cannot open POP inbox for '$UserName' on $Server\n"; my $msgCount=0; foreach my $msg ($POP3InboxFolder->messages(-15,-1)){ # Last 15 #$msg->decoded->print(\*STDERR); print "-" x 50 . "\n"; my $head = $msg->head; print "#Msg SENT on ", ($head->timestamp || 'unknown'), " = ", $head->get('Date') , " Interp=", POSIX::strftime(qq(%H:%M %d %b), localtime($head->timestamp)) +, "\n"; print "#RCVD:" , $head->get('Received', 0) , "\n"; foreach(reverse $head->get('Received')){ # Extract the TIME received.. my $Date = &ParseDate( $_ ) or next; print "#Extracted Rcv Date $Date=" . POSIX::strftime(qq(%H:%M %d %b), localtime($Date)) . "\n"; last; } print "#Subject=", $msg->subject , "\n"; my $sender = $msg->sender; $sender and print qq(#Sender:\t) ,$sender->format , qq(\n) ; for ($head->names){ print "#\t$_\t ", $head->get($_), ";\n" ; } print "-" x 50 . " $msgCount\n"; last if $msgCount++ > 18; } }

        Earth first! (We'll rob the other planets later)

      Hmmmm... Thanks for your suggestion, but I guess I forgot to mention two things. One, I am not running a POP mail server. Two, the email address that is being used does not have a mailbox... its only a pointer to the mail filter script. I do not want to store any incoming emails. Just strip the information I need, perform any needed functions on the information, then send a response to the sender and trash the original email. Also, this needs to be performed as soon as the email is received. Thanks again for your suggestion...
        I suggest you look at the Mail::Box module anyway. It is written in a way that is generic - it asbtracts the Mailbox - and is independent of the transport (which is POP3 in my case).

        You may be able to use the Message and Messager-header objects, or subclass them. Or at least get some ideas on how to structure mail - like I said - this is a very-well designed module, worth a peek.

            Earth first! (We'll rob the other planets later)

Re: Email modules
by bgreenlee (Friar) on Aug 24, 2004 at 05:46 UTC

    Have a look at Email::MIME, and some of the other Email::* modules. They're part of the Perl Email Project, the goal of which is to come up with something less complex and buggy than the Mail::* modules.

    -b