First, most of the email providers give you a way to form-fill an email template. So, you can just log into your admin portal, type out the form mail, then look at their API to find out how to deliver the list of addresses and names. That's the easiest way.

If you really want to use SMTP, maybe for reasons you haven't told us, then like corion mentioned, you first should think of how to resume the mailing after it gets interrupted, because it would be bad (and expensive) to have to re-start from the beginning of the list and send some of them twice. You can either sort the emails and log as you send them so that you know where to pick up from, or you could write your progress to a database table in a way that you can later select only the email addresses that haven't been sent the email yet. Another method is to make a "spool" table where you queue one record for each email that you want to send, then delete one row from that table after each email is sent. This lets you separate the seteps of preparing the data to email, and delivering the emails, so you can inspect the results of the first phase before you have sent anything, and if something is wrong you just delete all the records and try again. When the queue looks accurate, then you begin sending, and deleting the record or updating it with the results of the send attempt.

In your code, this looks suspicious:

my @to; for my $em ( @$records ) { push @to, @$em; }
It looks like each element of $records is an array of *fields*, right? with one field being the email and one field being the name? I would think you would just do
# Slice makes it return an arrayref of hashrefs my $records = $query->fetchall_arrayref({}); my $transport= ... for my $record (@$records) { mail($from, $record->{to}, $subject, $record->{name}); } sub mail { my ($from, $to, $subject, $name)= @_; my $html= .... # form-fill the name into an html template my $email= ... sendmail($email, { transport => $transport }); }

You should definitely use a persistent mail transport. Here's a snippet from one of my systems:

$transport= Email::Sender::Transport::SMTP::Persistent->new( host => $host, ssl => ($port == 465)? 1 : ($port == 587)? 'starttls' : 0, port => $port, $user? (sasl_username => $user) : (), $pass? (sasl_password => $pass) : (), debug => $log->is_trace, );

That makes one SSL connection to the server and then sends all the mail through it without needing to re-initialize the SSL each time. It's massively faster than re-connecting for each email.

If you're looking for a good way to assemble a quality email message, I recommend Email::MIME::CreateHTML. Here are some other snippets you might find helpful:

# Assuming you start with an HTML document for your email: $text= HTML::FormatText::WithLinks->new(unique_links => 1) ->parse($html);
(it's good practice to include the text-only version of your html email, and probably helps not getting flagged as spam)
# Because most mail clients don't properly process <style> blocks, # we have to embed the style onto each individual element. # This class does the job for us. my $inliner= CSS::Inliner->new(); $inliner->read({ html => $html, charset => 'utf8' }); $html= $inliner->inlinify;

I forget why my code is calling CSS::Inliner when it also sets inline_css => 1 in the options to create_html below. I'll let you discover if that's necessary :-)

# Build the email. The resolver will find all external images # and stylesheets and suck them in as multiple parts. my $email= Email::MIME->create_html( header => [ ], # we use the unicode-enabled setters, instead text_body_attributes => { charset => 'UTF-8', encoding => 'quoted-printable' }, text_body => encode('UTF-8', $text), # text gets assigned as-is body_attributes => { charset => 'UTF-8', encoding => 'quoted-printable' }, body => $html, # body gets assigned as body_str embed => 1, base => "https://YOUR_WEBSITE", # Prevent excessive lookups of resources object_cache => $self->resource_cache, inline_css => 1, %$args, ); # These methods properly handle unicode, which is why we use them # instead of passing these to the constructor $email->header_str_set(To => (ref $to eq 'ARRAY'? join(', ',@$to) : ''.$to)); $email->header_str_set(From => (ref $from eq 'ARRAY'? join(', ',@$from) : ''.$from)); $email->header_str_set(Subject => ''.$subject);

Note all the details about utf-8. Sadly Email::MIME::CreateHTML doesn't have nice support for that yet. Email::MIME doesn't really either - I mean the options and methods exist, they just aren't the defaults.


In reply to Re^3: Send email with recipient name by NERDVANA
in thread Send email with recipient name by frank1

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.