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

Hi Monks!
I am trying to attach multiple images to my HTML template file, but i need the values for the images to be out side of my email sub, and that is where it is not working. It works having the values inside of the sub email, but I would like to have these values in a dynamic way, to be easier to manipulate the HTML template. Any help will be great, thanks for looking!
I hope the code explains as well what I am trying to do here:
#!/usr/bin/perl use strict; use warnings; use MIME::Lite::TT::HTML; my %params; $params{first_name} = 'Joe'; $params{last_name} = 'Test'; $params{date} = 'April 11, 2011'; my %options; $options {INCLUDE_PATH} = '/templates'; my $logo = '/images/logo.gif'; my $footer = '/images/footer.gif'; # I'd like to have a system that would allow me # to add as many images as possible to my template file here # instead of multiple hashes, is that possible? my %img_in; $img_in{Type} = 'image/gif'; $img_in{Id} = 'logo'; $img_in{Path} = $logo; $img_in{Filename} = 'logo.gif'; $img_in{Disposition} = 'attachment'; my %img_sec; $img_sec{Type} = 'image/gif'; $img_sec{Id} = 'footer'; $img_sec{Path} = $footer; $img_sec{Filename} = 'footer.gif'; $img_sec{Disposition} = 'attachment'; # set up email my $to = 'test@test.com'; my $from = 'test@test.com'; my $subject = "Email Sent Test"; my $message = "Email Test."; # send email email($to, $from, $subject, $message); # email function sub email { # get incoming parameters my ($to, $from, $subject, $message) = @_; # create a new message my $msg = MIME::Lite::TT::HTML->new( From => $from, To => $to, Subject => $subject, Template => { #text => 'test_txt.tt', html => 'test_html.tt', }, TmplOptions => \%options, TmplParams => \%params, Data => $message ); # add the attachments # this works but I need these values to be dynamic not hard coded in +here =code my $logo = '/images/logo.gif'; my $footer = '/images/footer.gif'; $msg->attach( Type => 'image/gif', Id => 'logo', Path => $logo, Filename => 'logo.gif', Disposition => 'attachment' )or die "Error adding $logo: $!\n"; $msg->attach( Type => 'image/gif', Id => 'footer', Path => $footer, Filename => 'footer.gif', Disposition => 'attachment' )or die "Error adding $footer: $!\n"; =cut # here is where I am having problems for ( keys %img_in ) { $msg->attach( Type => $img_in{Type}, Id => $id=$img_in{ID}, Path => $path=$img_in{Path}, Filename => $img_in{Filename}, Disposition => $img_in{Disposition} )or die "Error adding $img_in{$_}: $!\n"; } # send the email $msg->send(); }
Here is the test template:
<html> <body> TEST HTML<br> Logo: <img src="cid:logo" height="36" border="0"> <br> <strong>Hi [% first_name %]</strong>, <p> Last Name [% last_name %]. </p> <p> [% date %] </p> <p> Thank you! </p> Logo Footer: <img src="cid:footer" height="36" border="0"> <br> </body> </html>

Thanks!

Replies are listed 'Best First'.
Re: Attaching images to email html template help!
by Eliya (Vicar) on Mar 17, 2011 at 17:15 UTC
    # I'd like to have a system that would allow me # to add as many images as possible to my template file here # instead of multiple hashes, is that possible? my %img_in; ... my %img_sec; ...

    If I'm understanding you correctly, you want an array of hashes holding the image info:

    my @imgs = ( { Type => 'image/gif', ID => 'logo', Path => '/images/logo.gif', Filename => 'logo.gif', Disposition => 'attachment', }, { Type => 'image/gif', ID => 'footer', Path => '/images/footer.gif', Filename => 'footer.gif', Disposition => 'attachment', }, # ... );

    (of course, you could also fill the hashes dynamically...)

    You should then be able to iterate over / attach them as follows

    for my $img (@imgs ) { $msg->attach( %$img ) or die "Error adding $img->{Filename}: $!\n" +; }
      That cleared some issues for me for sure, thank you, but the images is still only showing when the $->attach(); is inside of sub email for some reason.
        but the images is still only showing when the $->attach(); is inside of sub email

        To attach the images you need the $msg object, and as you have it, that object is lexically scoped to your email function.

        Anyhow, why do you want to attach the images outside of the function?

        I got it to work, the issue was with ID => 'logo',".
        It should be;
        Id => 'logo',

        I am curious about how I could fill the hashes dynamically, any example on that?
      Thanks for your response, it was a great help.
      If I change my sub routine "email" from my sample code here into a module and lets say I would be passing all the values to this new module now called mod_email like this;
      mod_email( {to=>$to, from => $email, subject=>$subject, body=>$body, ttparams => $templ_data} );
      There is no problem passing the values into the module like that, but how could I pass this array of hashes "@imgs" to this module? Here is some lines of code of my trying for your opinion:
      #from the .pl file call the module ... mod_email( {to=>$to, from => $email, subject=>$subject, body=>$body, t +tparams => $templ_data},imgs=>@imgs ); #now this part would be code inside of the module mod_email ... sub process_email_stuff { my ($vals) = @_; my $to = $vals->{ to } || {}; my $from = $vals->{ from } || {}; my $subject = $vals->{ subject } || {}; my $body = $vals->{ body } || {}; my $ttparams = $vals->{ ttparams } || {}; #questioning this: my @imgs = $vals->{ imgs } || {}; my $msg = MIME::Lite::TT::HTML->new( From => $from, ... #all the other stuff its done, now get to the @imgs processing, hopefu +lly. for my $img (@imgs ) { $msg->attach( %$img ) or die "Error adding $img- {Filename}: $!\n" +; } ... 1;

      I hope this is clear about want I am trying to accomplish, and thanks once again!
        how could I pass this array of hashes "@imgs" to this module?

        Normally, you'd pass a reference to it, i.e. \@imgs

        email( {to=>$to, from => $email, ..., imgs => \@imgs} ); ... sub email { my ($vals) = @_; ... my $imgs = $vals->{ imgs } || []; ...

        Further on, you then just dereference it the usual way: @$imgs for the entire array, or $imgs->[0] for a single element (which would be a hashref in your particular case).

        See also perlreftut and perlref.

        P.S. you probably don't want to supply an empty hashref ({}) as defaults for things which are normally just scalars/strings, such as your

        my $to = $vals->{ to } || {}; my $from = $vals->{ from } || {}; my $subject = $vals->{ subject } || {}; ...