Sending E-mail with Perl

Buggy Unportable Unscalable Error Prone Method | Portable Scalable Method | Message Content

Problems with and solutions to sending e-mail with Perl. Short on time? Try Email::Sender::Simple. See also Email Hates The Living. Do not, I repeat, do not attempt to send e-mail by piping data directly to sendmail or mail(1).

Buggy Unportable Unscalable Error Prone Method

Repeated far too often in code, despite various horrible flaws and limitations. Do not use!

open SENDMAIL, "|/usr/sbin/sendmail -t"
or die "$0: fatal: could not open sendmail: $!\n";
print SENDMAIL "To: user\@example.org\n";
print SENDMAIL "Subject: message\n\n";
print SENDMAIL "Message body\n";
close SENDMAIL;

Problems include:

Net::SMTP is another module I dislike: it does not support Mail Exchange (MX) records, and thus to avoid a single point of failure—the single host the module connects to—requires wrapping with additional code that looks up MX records, handles various temporary or permanent send failures, queues temporarily failed messages, and otherwise begins to poorly implement a proper Mail Transport Agent (MTA). The portable, scalable method, below, passes e-mail off to a local MTA, which handles the (many!) delivery complications of the Simple Mail Transport Protocol (SMTP). If the code cannot be fixed to not rely on a single host, then time must be wasted setting up a highly available address, usually via some expensive network device or complicated software load balancer, and a likely higher risk of e-mail delivery failure accepted.

Portable Scalable Method

Among the many Perl modules available on Comprehensive Perl Archive Network (CPAN) for sending e-mail, I favor MIME::Lite. Easy to use, easy to attach new content, and easy to send the message elsewhere for debugging:

use MIME::Lite;
my $message = MIME::Lite->new(
To => 'user@example.org',
Subject => 'message',
Data => 'Message body'
);
$message->send();

Consider also the Email::Sender::Simple module, or perhaps Email::Sender::Transport::SMTP if SMTP must be used or Email::Sender::Transport::SMTP::TLS for SMTP with TLS (SSL) support. Other options for MIME include Email::MIME. For more complex MIME messages, see Email::MIME::Kit::*.

Message Content

Never build up a message into a scalar, then print the scalar. HTML errors become difficult and time consuming to debug in longer messages, and extending or reformatting the look of the message is nearly impossible.

my $message_body = '<html></body>';
$message_body .= '<B>This is as ugly as it looks</B';
if ($printer_on_fire) {
$message_body .= "<p>More <a href=\"ugh\">horrors</a>";
}

Instead, template the message with HTML::Template or similar module. This abstracts the data properly away from the content. At the very least, stop backslashing doublequotes in doublequoted strings:

my $ugly = "<a href=\"$url\">$link_text</a>";
my $link = qq{<a href="$url">$link_text</a>};