Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Getting recommened_filename from MIME::Parser

by thatguy (Parson)
on Oct 16, 2001 at 10:52 UTC ( #119076=perlquestion: print w/ replies, xml ) Need Help??
thatguy has asked for the wisdom of the Perl Monks concerning the following question:

I've looked through the Super Search for examples of receiving attachments with MIME::Parser. I've been through the docs for Parser, MIME::Parser::Filer, and Parser::Head and for the life of me I cannot get the recomended filename for an attached file.

Anyone know what is causing the script to fail to find the suggested filename?

These are the errors I get with the various methods:
Method 1:
Can't call method "path" on an undefined value at ./mail_prog.pl line 59.
Method 2 & 3:
Use of uninitialized value in concatenation (.) or string at ./mail_prog.pl line 67

I have the three methods I've seen and tried below.

much thanks in advance.
-phill

#!/usr/bin/perl -w use Mail::POP3Client; use MIME::Parser; use MIME::Head; use strict; my $pop=new Mail::POP3Client( USER=>"xxxx", PASSWORD=>"xxxx", HOST=>"mail.example.com"); my $msgcount=$pop->Count(); my $msgnum; for $msgnum (1 .. $msgcount){ print "message number: $msgnum\n"; # get headers my $header=$pop->Head($msgnum); # get body my $body=$pop->Body($msgnum); # get whole message my $message=$pop->HeadAndBody($msgnum); my $parser=new MIME::Parser; # disable output to file/dir $parser->output_to_core(1); my $entity = $parser->parse_data($message); # get the number of parts of the message (if multipart) my $num_parts = $entity->parts; my @parts = $entity->parts; my $bodydata; if ($num_parts > 0) { # more than one part, mime-ahoy? my $part; for $part(@parts){ # get mime type my $type=$part->mime_type; my $bhandle=$part->bodyhandle; # special treatment for text and html if (($type =~ /text/i) || ($type=~ /html/i)){ if (my $io = $part->open("r")) { while (defined($_ = $io->getline)) { $bodydata .= $_; } $io->close; } print $bodydata,"\n"; } else { # must be an attachment of sorts or # at least not text/html my $content .= $bhandle->as_string if defined $bhandle; # method 1 # my $file_name = $entity->head->recommended_filename || # $entity->bodyhandle->path; # method 2 #my $mimehead=MIME::Head->new; #my $file_name=$mimehead->recommended_filename; # method 3 #my $file_name = $bhandle->{MB_Path}; print "path: $file_name\n"; # dump attachment to outfile # (works when name is specified) open(OUT,"> /path/to/attachments/$file_name"); # is this needed? local $/ = undef; print OUT $content,"\n"; close(OUT); } } } else { # plaintext or html! if (my $io = $entity->open("r")) { while (defined($_ = $io->getline)) { $bodydata .= $_; } $io->close; } print $bodydata,"\n"; } $entity->purge; } exit;

Comment on Getting recommened_filename from MIME::Parser
Download Code
Re: Getting recommened_filename from MIME::Parser
by projekt21 (Friar) on Oct 16, 2001 at 13:01 UTC

    I'm not sure if I can help you solve your problem ...

    Update (further research): I noticed three things:

    • As long as I use $parser->output_to_core(1); I don't get the path. Changing to $parser->output_under("/tmp"); does return a path.
    • Your for $part(@parts){ }-loop runs one iteration too often, so your error message comes from the last call, where no parts are left.
    • method 1: change $entity->bodyhandle->path; to $part->bodyhandle->path;.

    The following code works fine for me:

    use MIME::Parser; split_entity($entity); # $entity is a MIME::Entity object ################################################ sub split_entity { ################################################ local $entity = shift; my $num_parts = $entity->parts; # how many mime parts? if ($num_parts) { # we have a multipart mime message foreach (1..$num_parts) { split_entity( $entity->parts($_ - 1) ); # recursive call } } else { # we have a single mime message/part if ($entity->effective_type =~ /^text\/plain$/) { # text message handle_text($entity->bodyhandle->as_string); } else { # no text message handle_other($entity->bodyhandle->path); } } }

    As you can see, I use path as you did and it is working perfectly.

    I further recommend using a similar recursive call as some mailers seem to nest multipart messages and you maybe want to parse them correctly to any depth.

    alex pleiner <alex@zeitform.de>
    zeitform Internet Dienste

      Excellent! that works perfectly, thanks!
      -phill

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://119076]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2015-07-02 01:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (25 votes), past polls