Sending email in Perl

If you’ve been writing Perl for a few months, chances are good that at some point you will need to send emails from your scripts. As always with Perl, there’s more than one way to do it, but I think using Email::Simple and Email::Sender is a good trade-off between introducing dependencies (it’s not part of the standard Perl distribution) and re-using code.

The most basic self-contained script I could write for sending emails can be found below. Feel free to use this as a starting point for your own projects (there’s no error handling for example) – the main reason for posting it here is so that my future self can refer to it.

#!/usr/bin/env perl

use strict;
use warnings;
use autodie;

use Email::Sender::Simple;
use Email::Simple;
use Email::Simple::Creator;
use Email::Sender::Transport::SMTP;

my $from_address = 'someone@example.org';

my $email = Email::Simple->create(
  header => [
    To => 'someone@example.org',
    From => $from_address,
    Subject => 'Test from Email::Simple',
  ],
  body => 'This is a test message from Email::Simple',
);

my $transport = Email::Sender::Transport::SMTP->new({
  host => 'smtp.example.org',
});

Email::Sender::Simple->send($email, { from => $from_address, transport => $transport });

 

9 Comments

  1. Some years ago, I was using this solution in my Perl/Unix course, usint a file manager process.Regards.
    Sory, it is in french, but I think anyone can understant.

    Regards

    #!/usr/bin/perl
    while (1) {
    print “Entrez les donnees du mail\n”;
    print “Destinataire : “;
    chomp ($destinataire = );
    $nom = $destinataire;
    $nom =~ s/^\s*(\w+)@.*$/$1/;
    print “Expediteur : “;
    chomp ($expediteur = );
    print “Adresse de reponse : “;
    chomp ($repondre = );
    print “parametres.\n”;
    print “Destinataire : $destinataire.\n”;
    print “Nom : $nom.\n”;
    print “Expediteur : $expediteur.\n”;
    print “Repondre : $repondre.\n”;
    print “Les donnees sont-elles correctes (oui/non) ? “;
    chomp ($r = );
    last if $r eq “oui”;
    }

    # L’option -t pour intégrer les en-têtes fournies.
    open(MAIL,”|/usr/sbin/sendmail -t”) or
    die “impossible d’expedier par sendmail !”;
    # Attention à la syntaxe.
    # Un passage à la ligne entre chaque en-tete
    # Un : après chaque mot-clé
    $message=
    “From: $expediteur
    To: $destinataire
    Reply-To: $repondre
    Subject: Mail de Perl
    Bonjour $nom
    Tu viens de recevoir un mail.
    Envoye per un programme Perl.”;
    print “Mail expedie.\n”;
    print MAIL $message;
    close MAIL;

  2. Another nice module for mailing is MIME::Lite which has a nice and easy interface and is also low on dependencies. It’s from the same author as Email::Sender and both seem to be actively maintained.

    Ah, in the MIME::Lite documentation there’s this part:

    WAIT!
    MIME::Lite is not recommended by its current maintainer. There are a number of alternatives, like Email::MIME or MIME::Entity and Email::Sender, which you should probably use instead. MIME::Lite continues to accrue weird bug reports, and it is not receiving a large amount of refactoring due to the availability of better alternatives. Please consider using something else.

    I guess I should move to Email::Sender sometime soon as well then :-).

  3. Paul

    Chris: My French is a bit rusty but I can just about translate the code. 🙂 I suspect opening a file handle to sendmail will still work but I wouldn’t recommend it – especially now that local::lib makes it easy to install local copies of Perl modules.

    Christiaan: I came across the same issue with Email::Send – it was mentioned in Automating System Administration with Perl but when I checked the documentation it too pointed me to Email::Sender.

  4. I always recommend delivering via sendmail rather than SMTP where available. The SMTP case assumes you have network access to a functioning mail server that is not currently being DOS’d and isn’t greylisting you, etc – multiple potential points of failure. Whereas delivering via sendmail (using say Email::Sender::Transport::Sendmail) will put your message directly into the outgoing queue on the local host. Delivery will follow as network conditions permit and failures will be met with retries without any work from you.

  5. Hi! I wrote or maintain most of the code mentioned in the post and its comments, and I thought I’d weigh in. First: thanks for the post, and I’m glad you (seem to have) found the software useful!

    Your example might work just fine in most circumstances without the creation or use of an SMTP transport object. In general, Email::Sender::Simple will try to use `sendmail` safely if it exists, and will otherwise try SMTP on localhost. Of course if, as in your example, you must use a remote SMTP server, then you’ve got to do it!

    I wanted to point out that the interchangeability of transport objects is, for me, the greatest utility of Email::Sender. When testing, the SMTP transport can be replaced by a transport that delivers into an array in memory. For processes that send mail after forking, they can share a SQLite database to receive the mail for later examination. It makes it much easier to test email-sending code, which is often treated as a “well, we’ll test it in production” feature.

    In many cases, you can use these features through the environment. If you want to run a program and dump all its mail into a maildir for later inspection with mutt, you can just set EMAIL_SENDER_TRANSPORT=Maildir and run your program.

    I hope that extra information ends up proving useful! Happy hacking…

    • msouth

      Ricardo: this information would make a great standalone blog post!

  6. Paul

    Grant: I agree that sendmail is probably more reliable, although in most cases I’ve had to use a specific SMTP server for various policy reasons.

    Ricardo: Thanks for the extra information (and for writing the module!), the ability to use an SQLite database sounds like it could be really useful for debugging and development (at the moment I tend to use different recipients for development/production to handle email testing). I’ll have a look at the advanced features at some point and hopefully write a post about them.

  7. Joe

    For Chris: Your example is missing a blank line, that is critical.

    “Subject: Mail de Perl
    Bonjour $nom”
    needs to be
    Subject: Mail de Perl

    Bonjour $nom

Leave a Reply to Paul Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.