Sending a simple email: the current "modern" way

Some of my scripts are still set in stone age when it comes to the practice of sending emails. They almost invariably use Mail::Sendmail, a module that has not been updated since 2003 (and why should it if it doesn't break, right?). So far there's no complaints. The usual incantation for sending email using this module is:

use Mail::Sendmail;
mail(From=>$rfc_from, Sender=>$env_sender, Subject=>$subject, 
     To=>$rcpt, Cc=>$other_rcpt,
     Message=>$body) or warn "Can't send mail: $Mail::Sendmail::error";

But today I need to switch transport to sendmail. Despite what the name might suggest, Mail::Sendmail uses SMTP for transport and there's no alternative transport. There's also no support for SMTP auth, which my SMTP server now requires even for access from localhost. From what I read and tried once or twice in the past, the current "best practice" or recommended way is to use Email::Sender. Here's the incantation for sending mail using sendmail:

use Email::Sender::Simple qw(sendmail);
use Email::Simple;
use Email::Sender::Transport::Sendmail qw();
use Try::Tiny;

my $email = Email::Simple->create(
    header=>[To=>$to, From=>$from,
             Subject=>$subject],
    body=>$body,
);

try {
    sendmail($email,
             {from=>$from,
             transport=>Email::Sender::Transport::Sendmail->new});
} catch {
    print "Can't send mail: $_";
}

Okay, quite a bit longer and everything is fancy objectsie. But I think I'm okay with this because, like DBI, the incantation above is quite flexible and "scalable":

  • It's easy to switch transport to SMTP (just change two lines).

  • It's easy to add SMTP authentication (just pass arguments to transport constructor).

  • It's easy and clear where to add custom email headers (whereas in Mail::Sendmail, some arguments are "magical"/processed, they do not correspond 1:1 to headers).

  • It's easy to construct multipart email (construct the appropriate $email object).

In addition:

  • Envelope sender and RFC822 From is clearly separated, forcing beginners to understand the concept.

So there you have it, sending an email in Perl the modern way. No longer apt for one-liners though.

5 Comments

imo the link to Email::Sender should probably point to metacpan rather than metadata.

As an alternative I use 'Mail::Sender'. IMHO, it is easier to use and it has also an SMTP auth.

I tried the following:
use Email::Sender::Simple qw(sendmail);
use Email::Simple;
use Email::Sender::Transport::Sendmail qw();
use Try::Tiny;

$recipient = $_POST['recipient'];
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$from = $firstname + $lastname;
$subject = $_POST['subject'];
$body = $_POST['body'];

my $email = Email::Simple->create(
header=>[To=>$recipient, From=>$from,
Subject=>$subject],
body=>$body,
);

try {
sendmail($email,
{from=>$from,
transport=>Email::Sender::Transport::Sendmail->new});
} catch {
print "Can't send mail: $_";
}

and my host (GoDaddy) returned the following error:

The specified CGI application encountered an error and the server terminated the process.

Any ideas?

Leave a comment

About Steven Haryanto

user-pic A programmer (mostly Perl 5 nowadays). My CPAN ID: SHARYANTO. I'm sedusedan on perlmonks. My twitter is stevenharyanto (but I don't tweet much). Follow me on github: sharyanto.