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

Summary

Thank you. Code below.

sub getnetpop3 {my($l)=@_; my(@a,@b,$i,$j,$procname,$s,$t); my($f,$fndmsg,$user,$pw,$server,$conn,$msgtotal,$mboxsize,$myvalidexts +); my(%msgids,$headers,$header,$msgnum,$msgsize,$d,$m,$y,$savedir); my($msgsubj,$msgid,$minsize,$msg,@dirfiles); my($parser,$entity,@parts,$part,$path,$ext,$continue); my(@suffixlist,$fname,$fpath,$suffix); # From http://spideringhacks.org.ua/0596005776_spiderhks-chp-3-sect-9. +html $procname="getnetpop3"; $minsize=4000; # Minimum size of message to download in bytes. $server='pop.myserver.net'; $myvalidexts='xls'; # was 'jpg jpeg xls' $savedir='mimein'; # Save emails here. $conn = Net::POP3->new(Host=>$server, #Debug=>1, Timeout=>480, # More Seconds for debugging ) or die "$procname ERROR: Could not connect to $server\n"; $user='user@somewhere.com'; $pw='catdog'; $t=localtime(); $conn->login($user,$pw) or die "$procname ERROR: Could not login to $s +erver.\n"; ($msgtotal,$mboxsize)=$conn->popstat(); # Get total msgs and mailbox s +ize in bytes. if ($msgtotal==0) { print "$procname ERROR: $t No emails available to process.\n"; exit; } if ($msgtotal==0) { print "$procname ERROR: $t No emails available\n"; exit; } #print "You have $msgtotal messages totalling ".Commafy($mboxsize)." b +ytes\n"; $msgnum=1; # Get first message. print "=" x 50, "\n"; # Visual separator while ($msgnum<=$msgtotal) { $msgsubj=''; $msgid=''; $fromaddr=''; $msg=''; $fndmsg=''; $msgsize=$conn->list($msgnum); # Get size of one msg in bytes. # Do not process small messages. if ($msgsize>$minsize) { $headers=$conn->top($msgnum); # Returns ref to array. foreach $header (@$headers) { if ($header=~m/^Subject: (.*)/) { $msgsubj=substr($1,0,50); # Trim subject down a bit #print "Msg $msgnum: ".Commafy($msgsize)."b, Subject: +$msgsubj\n"; } elsif ($header=~m/^From: (.*)/) { $fromaddr=$1; # Who sent the email } elsif ($header=~m/^Message-ID: <(.*)>/i) { $msgid=$1; $msgids{$msgid}++; } elsif ($msgsubj and $msgid) { last; # Exit foreach } } # foreach $header $fndmsg=" Found msg $msgnum with valid size ".Commafy($msgsiz +e).", From: $fromaddr, subject: $msgsubj"; print $fndmsg."\n"; # Error after getting first mgs. $msg=undef; eval { $msg=$conn->get($msgnum); }; # Get one email. if ($@) { $s=" $procname ERROR: Could not get msgnum $msgnum."; writeerr($s); goto netpop3exit; } # Below may never execute on error. if (!($msg)) # If $msg is undefined show error. { $s=" $procname ERROR undefined msg: $msgnum\n"; writeerr($s); goto netpop3exit; } $parser=new MIME::Parser; $parser->output_dir($savedir); # Do not use subdirs. All parts + in one subdir. $entity=$parser->parse_data($msg); # Returns ref to array and +saves files to disk. Debug: x @$msg # Extract MIME parts and go through each one. # Each item in @parts is also a MIME::Entity. # But not if the $parts[n]->effective_type is 'multipart/*' or + 'message/*'. # Each $part is a MIME::Entity object. @parts=$entity->parts; # All MIME parts of current message. foreach $part (@parts) # Get next part of MIME. { $path=''; # See also $parts[1]->mime_type. # See also $part->effective_type. $path=($part->bodyhandle) ? $part->bodyhandle->path : unde +f; next unless $path; $path=~m/\w+\.([^.]+)$/; $ext=$1; next unless $ext; # If $ext defined, then process file. # Now delete unwanted file extensions from PC. unless ($myvalidexts=~m/$ext/) { # Delete temp MIME file unless it's a wanted extension +. unlink $path or print " ERROR removing file at $path; + $!.\n"; next; # Get next item in loop. } # unless print " FOUND valid file: $path\n"; # Move files from $savedir to ../in. First get base name. ($fname,$fpath,$suffix) = fileparse($path,@suffixlist); $t='in/'.$fname; if (-e $path) { if (!(copy($path,$t))) { $s= " $procname ERROR: Could not copy $path to $t +.\n $!"; writeerr("$s"); } } # Check for valid XLS files for this sender and process th +em. # If no files, just exit with no msg. @files=glob($savedir.'/*.xls'); # Process all XLS files in this email msg. proc1xls($fromaddr,\@files); # Delete incoming email from POP3 server here # only if it has an XLS attachment. if (($path=~m/\.xls$/) and ($optdelete eq '-delete')) { if ($conn->delete($msgnum)) { $s=" Deleted msg $msgnum, Subj: $msgsubj. "; writeerr($s); } else { $s="$procname ERROR: Could not delete message from + $server: $msgnum"; writeerr($s); } } } # foreach $part } # If msgsize > minsize $msgnum++; # Get next msg. } # while netpop3exit: $conn->quit; # Now remove non-attachements. chdir($savedir); opendir(SAVE, "./") or die "$!"; @dirfiles=grep !/^\.\.?$/, readdir(SAVE); closedir(SAVE); foreach $f (@dirfiles) # Delete temp files. { if (!(unlink $f)) { $s=" $procname ERROR1: Could not delete $f. $!"; writeerr($s); } } chdir('..'); return; # getnetpop3 } ###################################################################### +##### sub writeerr {my($l)=@_; #print ERRFILE "$l\n"; print "$l\n"; #push(@errors,$l); return; # writeerr }

EDIT: I'd like to delete this thread but don't see a way how. I got around this by ignoring the entity object and simply searching for XLS files in my subdir.

Perl 5.8.8 on Redhat Linux RHEL 5.5.56 (64-bit)
  • Comment on Having trouble getting all parts of email message via MIME::Parser
  • Download Code

Replies are listed 'Best First'.
Re: Having trouble getting all parts of email message via MIME::Parser
by McA (Priest) on Jul 07, 2014 at 13:52 UTC

    Hi,

    please, reduce your problem. Get rid of the whole fetching and storing stuff. Please provide a litte plain mail text ($msg in your program) which then gets parsed. Isolate the parsing step via function from the rest.

    In this case anybody here can run the parser on his or her machine and have a look at your problem.

    Regards
    McA

Re: Having trouble getting all parts of email message via MIME::Parser
by Anonymous Monk on Jul 07, 2014 at 13:47 UTC
    sub getnetpop3 {my($l)=@_; my(@a,@b,$i,$j,$procname,$s,$t);
    That's really hard to read (aka write-only Perl). And does your function have to be so big? You should probably start with refactoring the whole thing.