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

I'm trying to write a script that will access a gmail account and locally save the attachments on recent emails. My code below is saving the file when there is a new email with an attachment in the account, however the result is corrupt (I've only been trying with PDFs, but I presume this happens with all filetypes) - the files are partially legible but large parts are simply blank.

Any ideas?
use Mail::POP3Client; use Email::MIME; use Email::MIME::Attachment::Stripper; my $pop = new Mail::POP3Client( USER => 'user', PASSWORD => "password", HOST => "pop.gmail.com", USESSL => 'true', ); print "Status: ". $pop->State()." No of email:". $pop->Count(); if ($pop->Count()) { my $mail=$pop->HeadAndBody(1); my $parsed = Email::MIME->new($mail); my $stripper = Email::MIME::Attachment::Stripper->new($parsed); my @attachments = $stripper->attachments; foreach my $att ( @attachments ) { open (FILE, ">>" . $att->{filename}); print FILE $att->{payload}; close (FILE); } } $pop->Close(); exit;

Replies are listed 'Best First'.
Re: Downloading Gmail attachments - Corrupted saved file
by ikegami (Patriarch) on Dec 30, 2009 at 22:53 UTC
    open (FILE, ">:raw:perlio" . $att->{filename});

    :raw removes default layers which may transform the data being printed. :perlio reintroduces buffering.

    > instead of >> replaces existing files instead of corrupting existing files by appending to them.

    Update: Added explanations.

      ikegami, I just tried rewriting that one line and there was no output.

        The concatenation dot should've been a comma:

        open (FILE, ">:raw:perlio" . $att->{filename}); ^

        To specify PerlIO layers, you need the 3-argument form of open. Otherwise, the name of the file you try to create will literally start with ":raw:perlio"...

Re: Downloading Gmail attachments - Corrupted saved file
by localshop (Monk) on May 13, 2013 at 23:15 UTC
    A couple of points. If you are running on Windoze you may want to write the files in binary mode (see binmode). Also it looks to me as though you are trying to append the files instead of writing to them. Here's my code that works ok:
    foreach my $at ( @attachments ) { if ( $at->{content_type} =~ /pdf/i ) { open(my $fh, '>', $at->{filename} ) || die ( $!); binmode $fh; print $fh $at->{payload}; $fh->close(); } }