Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

MIME::Tools to save attachment properly

by gcasa (Novice)
on Jul 09, 2015 at 16:40 UTC ( [id://1133987]=perlquestion: print w/replies, xml ) Need Help??

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

Good Day Monks! Thank You for sharing your wisdom!!!

I am attempting to save an "attachment" from an email. My code saves the present attachment which is a 7-zip file. Alas, when I attempt to open the file with 7-zip, it balks stating the file is not an archive.

I have pieced my code together from the examples I have found. Most examples seem to elaborate on constructing a message. I am wanting to deconstruct a message. :-)

What have I done wrong?

Thank You again for sharing your time and knowledge!!!

glenn

=====

#!/usr/bin/perl -w use Carp; use MIME::Parser; use strict; use warnings; my $parser = MIME::Parser->new( ); $parser->output_under( "tmp" ); #write attachments to disk my $entity = $parser->parse(\*STDIN); # die( )s if can't parse my $header = $entity->head( ); # object--see docs my $preamble = $entity->preamble; # ref to array of lines my $epilogue = $entity->epilogue; # ref to array of lines my $num_parts = $entity->parts; my @parts = $entity->parts; #get email headers my $from = $header->get('From'); my $to = $header->get('To'); my $subject = $header->get('Subject'); chomp( $from ); chomp( $to ); chomp( $subject ); print " From: $from\n"; print " To: $to\n"; print " Subject: $subject\n\n"; print "Number of Parts: $num_parts\n\n"; print " Head: $header\n"; print " Preamble: $preamble\n"; print " Epilogue: $epilogue\n"; print "________________\n\n"; if( $num_parts > 0 ) { # more than one part my $part; for $part( @parts ) { # get mime type my $type = $part->mime_type; my $bh = $part->bodyhandle; print "MIME Type: $type\n"; my $content .= $bh->as_string if defined $bh; open( my $OUTFILE, ">", "output.7z" ); print $OUTFILE "$content"; close( $OUTFILE ); }; };

Replies are listed 'Best First'.
Re: MIME::Tools to save attachment properly
by scorpio17 (Canon) on Jul 09, 2015 at 20:30 UTC
    Try adding:
    binmode($OUTFILE);
    after the 'open', but before the 'print'.

      That was my missing link! Thank You!!!

Re: MIME::Tools to save attachment properly
by atcroft (Abbot) on Jul 09, 2015 at 17:55 UTC

    In the "Other I/O" section of the MIME::Body documentation, the following examples are shown:

    ### Dump the ENCODED body data to a filehandle: $body->print(\*STDOUT); ### Slurp all the UNENCODED data in, and put it in a scalar: $string = $body->as_string; ### Slurp all the UNENCODED data in, and put it in an array of lines: @lines = $body->as_lines;

    Why not, then, do something such as this (untested)?

    for $part( @parts ) { my $type = $part->mime_type; my $bh = $part->bodyhandle; print "MIME Type: $type\n"; if ( defined $bh ) { open( my $OUTFILE, ">", "output.7z" ) or die $!; $bh->print(\$OUTFILE); close( $OUTFILE ); } }

    Also, have you looked at the output.7z file that was generated to see if perchance it was encoded (Base64, Quoted-Printable, etc.), or if there was perhaps miscellaneous characters at the beginning causing 7zip to think the file invalid?

    Hope that helps.

    Update: 2015-07-09
    Added additional question regarding output.7z file.

      Thank You for the Replies!

      I just updated the code to reflect these changes. Alas, I received the same result.

      The MIME section of the message has the following information:

      ----boundary_0_a3691d3d-2344-4a85-be2b-f56c7108c983 Content-Type: application/octet-stream; name="settings.ace.2015-06-29.181909.(Error).log.7z" Content-Transfer-Encoding: base64 Content-Disposition: attachment

      Is there something I need to tell MIME::Tools specifically for Content-Transfer-Encoding?

      Thank You!

Re: MIME::Tools to save attachment properly
by Laurent_R (Canon) on Jul 09, 2015 at 17:49 UTC
    Hum, I've never tried something exactly like this, but maybe you should take a look at the Convert::UU module to uuencode and uudecode the binary zipped file.

    But there may be some mail modules taking care of that for you.

Re: MIME::Tools to save attachment properly
by Anonymous Monk on Jul 09, 2015 at 20:54 UTC

    What have I done wrong?

    My guess you didn't start with mimeexplode

      Going to have to check that example. Thank you for the pointer!

Re: MIME::Tools to save attachment properly
by sachss (Sexton) on Jan 24, 2017 at 02:33 UTC
    I am trying to parse an email from Yahoo with split-7z files attached to them. I was able to log in successfully into Yahoo with Net::IMAP::Simple, which was assigned to $server. my code
    my $parser = MIME::Parser->new( ); my $entity = $parser->parse_data(join '', @{$server->get($i) +}); my $numParts = $entity->parts; my @parts = $entity->parts; if ($numParts > 0) { foreach my $part (@parts) { my $type = $part->mime_type; my $bh = $part->bodyhandle; print "MIME Type: $type\n"; if (defined $bh) { open(my $OUTFILE, ">", $bh->path) or die $!; binmode($OUTFILE); $bh->print(\$OUTFILE); close($OUTFILE); } #End IF $bh defined } # End For Each Part } # End If Num of Parts > 0
    When I run this, I get

    msg-1304-1.txt of size 826

    msg-1304-2.html of size 2,661

    _Archive.7z.046 of size 0, when it should be 8,975,069

    All I care about is the _Archive.7z.001 thru _Archive.7z.046

    Help me O' Great Monks

      Have you looked at the ->mime_type and the other attributes of the attachment?

      Are you certain that the attachment itself is OK in the mail?

      Have you inspected the raw data before parsing it? Maybe it is broken in some way that MIME::Parser doesn't handle?

        I liked at ->mime_type which is "application/octet-stream", but I am not aware of other information options.

        The attachment in the actual email is fine as far as I can tell. I have about 46 emails, each with a single attachment, which is about 10 Mb, which composes a 460 Mb 7z file as a whole.

        How do I check the raw data? I thought that was what I was trying to output, which comes out as zero-length, although, spot-checking would suggest it might be being overwritten for some reason, as I do see a non-zero length during then zero-length at the end.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-03-29 10:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found