Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

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

by kazak (Beadle)
on May 20, 2012 at 16:24 UTC ( [id://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 => 'reporter@example.com' ], 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:
      ./report_sender.pl 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 example.com (mrbap4) Welcome to Zeus +ESMTP server Net::SMTP=GLOB(0x15ff3b0)>>> EHLO localhost.localdomain Net::SMTP=GLOB(0x15ff3b0)<<< 250-example.com 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:<reporter@example.com > Net::SMTP=GLOB(0x15ff3b0)<<< 250 OK Net::SMTP=GLOB(0x15ff3b0)>>> RCPT TO:<dummy72@gmail.com> 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: user@example.com Net::SMTP=GLOB(0x15ff3b0)>>> From: reporter@example.com 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 example.com 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?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2024-03-28 19:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found