Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

[Resolved]Email::Mime 1 email + multiple attachments

by kazak (Beadle)
on May 20, 2012 at 16:24 UTC ( #971497=perlquestion: print w/replies, xml ) Need Help??
kazak has asked for the wisdom of the Perl Monks concerning the following question:

Hi, to all. I'm trying to add multiple attachments with Email::Mime to 1 email. Script executed by schedule and checks MySQL DB in order to get recipients list, attachment list, etc. I managed to implement my idea but not like I wanted. (For each recipient script compiles his own e-mail and attaches 1 file, in result 1 recipient will not receive 1 e-mail with 3 attachments, but 3 e-mails with 1 attachment in each e-mail.) The main problem for me is: If I'm trying to access "@parts" outside of "foreach loop", @parts are empty, so I definitely doing something wrong, but I can't find where, thanks in advance.

Here is the piece of code and attachment list format:

Attachment list may look like this: summary.csv,weekly.csv,john.csv

my @files = split /,/,$Attachment; foreach (@files) { chomp; my $f_name = $_; $f_name =~ s/\/root\/Helpers/reports\///; print "FILENAME:$f_name\n"; my @parts = ( Email::MIME->create( attributes => { filename => "$f_name", content_type => "application/x-7z-compressed", disposition => "attachment", encoding => "base64", name => "$f_name", }, body => io( $_ )->all, ), ); $email = Email::MIME->create( header_str => [ From => '' ], parts => [ @parts ], header_str => [ To => $To ], header_str => [ Subject => $Report_name ], ); $email->filname_set($f_name); $email->name_set($f_name); my $eml = $email->as_string; }

Replies are listed 'Best First'.
Re: Email::Mime 1 email + multiple attachments
by Eliya (Vicar) on May 20, 2012 at 17:13 UTC
    recipient will not receive 1 e-mail with 3 attachments, but 3 e-mails with 1 attachment in each e-mail

    That's not too surprising, as your foreach loop is around everything.  Instead, create the list of attachments first, and then create one email to which you pass the list of attachments (@parts). I.e.

    ... my @parts; foreach (@files) { push @parts, Email::MIME->create( # attachments ... ); } $email = Email::MIME->create( # actual email ... parts => [ @parts ], ... ); ...
      I've done so before asking, sorry I forgot to mention about this. If I'm trying to access @parts not in "foreach" @parts are empty. Like yesterday:
      ./ Last execution date, not found for: Weekly summary DATE:2012-05-19 TODAY:2012-05-19 NEXT:2012-05-19 report: credentials last executed: 2012-05-19 next scheduled: 2012-05-19 FILENAME:Servers.7z FILENAME:weekly_sites.7z Net::SMTP>>> Net::SMTP(2.31) Net::SMTP>>> Net::Cmd(2.29) Net::SMTP>>> Exporter(5.63) Net::SMTP>>> IO::Socket::INET(1.31) Net::SMTP>>> IO::Socket(1.31) Net::SMTP>>> IO::Handle(1.28) Net::SMTP=GLOB(0x15ff3b0)<<< 220 (mrbap4) Welcome to Zeus +ESMTP server Net::SMTP=GLOB(0x15ff3b0)>>> EHLO localhost.localdomain Net::SMTP=GLOB(0x15ff3b0)<<< Net::SMTP=GLOB(0x15ff3b0)<<< 250-STARTTLS Net::SMTP=GLOB(0x15ff3b0)<<< 250-AUTH LOGIN PLAIN Net::SMTP=GLOB(0x15ff3b0)<<< 250-AUTH=LOGIN PLAIN Net::SMTP=GLOB(0x15ff3b0)<<< 250-SIZE 120000000 Net::SMTP=GLOB(0x15ff3b0)<<< 250 HELP Net::SMTP=GLOB(0x15ff3b0)>>> AUTH LOGIN Net::SMTP=GLOB(0x15ff3b0)<<< 334 VXNlcm5hbWU6 Net::SMTP=GLOB(0x15ff3b0)>>> cmVwb3J0ZXJAZGlhbG9nLXdlYmRlc2lnbi5kZQ== Net::SMTP=GLOB(0x15ff3b0)<<< 334 UGFzc3dvcmQ6 Net::SMTP=GLOB(0x15ff3b0)>>> cmVwb3J0ZXJxYXo= Net::SMTP=GLOB(0x15ff3b0)<<< 235 Authentication successful Net::SMTP=GLOB(0x15ff3b0)>>> MAIL FROM:< > Net::SMTP=GLOB(0x15ff3b0)<<< 250 OK Net::SMTP=GLOB(0x15ff3b0)>>> RCPT TO:<> Net::SMTP=GLOB(0x15ff3b0)<<< 250 OK Net::SMTP=GLOB(0x15ff3b0)>>> DATA Net::SMTP=GLOB(0x15ff3b0)<<< 354 Enter mail, end with "." on a line by + itself Net::SMTP=GLOB(0x15ff3b0)>>> To: Net::SMTP=GLOB(0x15ff3b0)>>> From: Net::SMTP=GLOB(0x15ff3b0)>>> Subject: credentials Net::SMTP=GLOB(0x15ff3b0)>>> Date: Sat, 19 May 2012 19:26:23 +0200 Net::SMTP=GLOB(0x15ff3b0)>>> MIME-Version: 1.0 Net::SMTP=GLOB(0x15ff3b0)>>> Content-Disposition: inline Net::SMTP=GLOB(0x15ff3b0)>>> Content-Type: text/plain; charset="us-asc +ii" Net::SMTP=GLOB(0x15ff3b0)>>> . Net::SMTP=GLOB(0x15ff3b0)<<< 250 Message 0LiUtY-1Rw1Ew1QTc-00crW0 acce +pted by Net::SMTP=GLOB(0x15ff3b0)>>> QUIT Net::SMTP=GLOB(0x15ff3b0)<<< 221 OK
        If I'm trying to access @parts not in "foreach" @parts are empty.

        You don't show the updated code, but my guess would be that you still have my @parts = ... within the foreach loop (like in your OP), instead of declaring the @parts array outside of the loop (like in the code I outlined).

        If you declare it within the loop, it's lexically scoped to the loop, i.e. not accessible outside of it.  Also, you'd create a new array instance on every iteration, instead of accumulating stuff in it.

        Sorry Eliya, this was my bad. It's true that I tried to use "@parts" outside foreach, BUT I used "@parts =" instead of "push" and this was main problem. You were absolutely right when you wrote your reply to me. Thank you very much.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://971497]
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (17)
As of 2018-07-23 14:01 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (469 votes). Check out past polls.