Sending Email with Perl Best Practice

Forward

If you are a spammer or otherwise send unsolicited bulk Email, please
stop reading this article now. This article has been specially crafted
to work poorly for spamming*.

Do everyone on the Internet a favor and find another way of making
your living. I firmly believe there is a special section of Hell
reserved for your kind.

Intro

One of the best things about programming in Perl is that there is more
than one way to do it ( aka TIMTOWTDI ), but the sheer number of
available options often confuses new programmers. My advice
to aspiring Perl programmers is to take a quick look at the
overall landscape of choices you have, ask fellow Perl programmers
you respect, pick the one that is the most flexible tool, and use it
in all of your code. You should only deviate from your standard
approach as a matter of last resort.

There are about 937 different ways to send Email with Perl. Having
been an active Perl developer for over 10 years, in the
past I've used such techniques as:

shelling out to /usr/sbin/sendmail

writing my own in-house modules

using Net::SMTP directly when the application did not need to
send attachments

But as anyone who has been involved with Perl for awhile knows, it's a
good idea to re-evaluate your current practices to see if a better
tool or technique has been developed since last time you researched it.

I recently re-evaluated how I send Email and I've fully switched to using
MIME::Lite::TT::HTML, in my opinion this is the best all
around Email tool available from CPAN today.

It allows you to:

Send your message via the local sendmail or via SMTP.

You can craft your message with templates (one for plain text and
a separate template for a HTML version). As the name suggests this
is done with Template Toolkit templates.

It easily handles attachments.

It is sufficient from a performance perspective.

If you don't need the ability to have an HTML version of your message,
you can simply use MIME::Lite::TT instead. It works in the same way
as MIME::Lite::TT::HTML, but only gives you the option of one plain text
template per message. The only difference in syntax is instead of passing
a hash with two arguments for the Template argument, you pass the filename
of the single plain text template.

Why use templates for Email?

You might be asking yourself why would you want to use templates for
building your messages. I agree most automated messages, such as
those generated by "I forgot my password to your site" links, are small
and the benefit of using templates might seem dubious at best.

However, I can guarantee that you will have to, at some point, make a
change to the text of the messages, fix a HTML rendering bug, etc.
during the production life of your code.

So why hard code it into your application? I see Email as just another
View ( in a MVC sense ) of the data and as such, the presentation
should be separated from the data. Using templates in this manner
also opens up the door to building more reusable components.

Using templates for Email, much like with a website or web application,
makes it easy to re-skin an existing application. This could be
just to get a new design or look, or possibly to re-purpose an application
for something it was never really intended for. If you have thinks
'Thank you from the XYZ.com Company' hard coded all over your application
this type of repurposing is difficult at best.

Using MIME::Lite::TT::HTML

Using MIME::Lite::TT::HTML is thankfully very simple. You create
an instance of the object and pass it a few parameters, such as
To/From addresses, Subject, the templates to use, and the data to
use when filling in the templates. Here is a simple example:

test.html.tt

If you notice, neither of the templates used the last name that was
provided in the %params hash. This was done to illustrate that you can
pass in more data than your templates will actually use. This can be handy
because you can pass in all of the related data ( in this case all of the
information about the purchase ) during development and then only use the
portions you want in production. This way there is no need to constantly
adjust your Perl code to match changes in your TT templates.

Sending Email with attachments

Now let's complicate our example above a tiny bit by sending along a
PDF receipt of their order. To do this we just add these lines of Perl
between the creation of the MIME::Lite::TT::HTML object and the call to
send it:

That is all there is too it. You set the file to be attached's MIME
type, the path on disk to where the file is location, the name you
would like to give the file, and note that it should be included as
an attachment.

Note that you need to ensure the MIME type you are using matches
the file to be attached. For example, you shouldn't use 'application/pdf'
if you are sending an image in the GIF format, you would set it to
'image/gif' instead. I might also be a good idea to customize the
Filename option so the user doesn't end up getting 01234942983423.pdf and
not be able to recognize it later. Perhaps something along the lines of
'mystore-receipt-2007-05-29.pdf'.

Sending without Sendmail

If you need to send your message not using a local sendmail installation,
but instead via a remote SMTP server you need to adjust the code to be:

$msg->send('smtp', 'smtp.yourisp.com', Timeout => 60 );

Which tells MIME::Lite::TT::HTML to use Net::SMTP in the background to
do the actual sending, that it should use smtp.yourisp.com, and have a
timeout value of 60 seconds. Everything after the first argument is
simply passed on to Net::SMTP.

Other Options

Some other options you might find useful to when working with
MIME::Lite::TT::HTML are:

Cc

Cc other addresses

TimeZone

Set the time zone of the sender of the message.

Encoding

Which encoding method to use for the body, the default is to use
7bit encoding. Other options are 8bit, quoted-printable, and
base64.

Charset

Set the character set of the message body, for example 'utf8'.

Sometimes it is desirable to create the message, but not send it. Because
MIME::Lite::TT and MIME::Lite::TT::HTML use MIME::Lite internally all of
the various MIME::Lite methods are also available. So instead of sending
the message on directly you can:

$msg->as_string

Generate the entire message as text as a string

$msg->header_as_string

Generate just the message header as a string

$msg->body_as_string

Generate just the body of the message as a string

Conclusion

Hopefully I've shown you the benefits of using templates for your Email
sending code, and specifically the benefits of MIME::Lite::TT::HTML. If
you have any questions, comments, or corrections please contact me at
frank@revsys.com.