How to Send Emails with Perl

If you program in Perl, you’re not short on options for sending emails from a Perl app. You can try Perl’s generic libraries and use external modules. Heck, if you don’t like any of these options, you can build your own module, and you won’t have to spend the next week doing so.

In this article, we’re going to cover several of the best approaches. We’ll explain who they will be the most useful for and how to implement them into your project. Let’s start!

Sending Emails with Sendmail

First things first, you might have come across the sendmail utility inside your Perl application.

It’s not a bad approach. Though, don’t expect excellent delivery rates. In our tests, a number of emails not only skipped the inbox, but they didn’t even “qualify” to be marked as spam.

Sendmail is super quick and simple to set up as long as you’re on a Linux/Unix machine. For Windows and other devices, you’ll need to look at alternative approaches. 

Make sure you configured sendmail properly, and let’s try sending a few sample emails.

Sending a Plaintext message

Here’s an example code for sending an email with sendmail:

#!/usr/bin/perl
 
$to = 'jane@mailtrap.io';
$from = 'piotr@mailtrap.io';
$subject = 'w00t it works!';
$message = 'Look at me, Jane. I’m sending emails from Perl!';
 
open(MAIL, "|/usr/sbin/sendmail -t");
 
# Email Header
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n\n";
# Email Body
print MAIL $message;

$result = close(MAIL);
if($result) {  print "Email Sent, Bro!\n";} else {  print "There was a problem, Bro!\n";}

What just happened? We configured variables — the address we send from ($from) and the recipient’s address ($to). We also specified the subject and a message. 

We then opened the sendmail utility, inserted all these details and added the message to a sending queue on your localhost. If you have a mail server setup, Jane should see our miserable attempt in her inbox in a few seconds. 

If you don’t, make sure sendmail is configured properly on your machine and that the recipient’s email service doesn’t block emails coming from your IP address.

Sending HTML Emails

The sample copy above will be fine for simple testing purposes or internal error reporting. If you, however, want to send emails to your users (or just want to make a better impression on Jane), you will want to use some HTML in the email body.

By default, sendmail sends emails in plain text. You can, however, enable HTML formatting by simply adding “Content-type: text/html” in the header part of the email.

#!/usr/bin/perl
 
$to = 'jane@mailtrap.io';
$from = 'piotr@mailtrap.io';
$subject = 'It's me again';
$message = '<p>Hey Jane!</p>
<p>Still reading my emails?</p>
<p>If so, I brought you some flowers!</p>
<p><img src="https://media.giphy.com/media/JI2HICt36nqta/giphy.gif" /></p>
<p>See you Thursday night maybe?</p>
<p>P.</p>';
 
open(MAIL, "|/usr/sbin/sendmail -t");
 
# Email Header
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n";
print MAIL "Content-type: text/html\n\n";

# Email Body
print MAIL $message;

close(MAIL);
print "Email Sent, Bro!\n";


Adding CC and BCC fields

It is no surprise that you can also add CC and BCC fields to your message headers.

#!/usr/bin/perl
 
$to = 'kate@mailtrap.io';
$from = 'piotr@mailtrap.io';
$cc = 'mary@mailtrap.io, ann@mailtrap.io, alice@mailtrap.io';
$bcc = 'jane@mailtrap.io';
$subject = 'Hello, it's me';
$message = 'I was wondering if after all these years you'd like to meet';
 
open(MAIL, "|/usr/sbin/sendmail -t");
 
# Email Header
print MAIL "To: $to\n";
print MAIL "From: $from\n";print MAIL "Cc: $cc\n";print MAIL "Bcc: $bcc\n";print MAIL "Subject: $subject\n\n";

# Email Body
print MAIL $message;

close(MAIL);
print "Email Sent, Bro!\n";

Adding an Attachment

It’s also possible to add an attachment to a message, but it’s a bit more complex. Note that each file will be loaded to the memory twice. So, adding large files is probably a poor idea.

Before running the code below, make sure the Mail::Sendmail module is already installed. 

use MIME::QuotedPrint;
use MIME::Base64;
use Mail::Sendmail;
%mail = (  from => 'john@mailtrap.io',  to => 'piotr@mailtrap.io',  subject => 'This is the last warning'
);

$boundary = "====" . time() . "====";
$mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\"";

$message = encode_qp( "Piotr, you really need to stop emailing your female colleagues at work. Attached you will find the list of complaints I received." );

$file = $^X; # This is the perl executable

open (F, $file) or die "Cannot read $file: $!";
binmode F; undef $/;
$mail{body} = encode_base64(<F>);
close F;

$boundary = '--'.$boundary;
$mail{body} = <<END_OF_BODY;
$boundary
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

$message
$boundary
Content-Type: application/octet-stream; name="$^X"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="Complaints.pdf"

$mail{body}
$boundary--
END_OF_BODY

sendmail(%mail) || print "Error: $Mail::Sendmail::error\n";


Test Your Emails Now

Sending Emails with MIME::Lite

Let’s move on to different approaches because sending without sendmail is definitely possible. Even better — alternative approaches such as MIME::Lite module offer more flexibility and are also available for non-Linux/Unix machines. You get all of this, without sacrificing the simple process of sending emails.

To install, simply insert the following code:

cpan -i MIME::Lite

Alternatively, download the module from MIME-Lite-3.01.tar.gz and install it with the following code:

tar xvfz MIME-Lite-3.01.tar.gz
cd MIME-Lite-3.01
perl Makefile.PL
make
make install

Sending a Plaintext message

As you would expect from a module with the word ‘lite’ in its name, sending in plain text is extremely simple. Here’s an example:

#!/usr/bin/perl
use MIME::Lite;
 
$to = 'jane@mailtrap.io';
$cc = 'john@mailtrap.io';
$from = 'piotr@mailtrap.io';
$subject = 'Apologies';
$message = 'Hey, I’m really sorry for the 132 emails I sent you last quarter.';

$msg = MIME::Lite->new(
                 From     => $from,
                 To       => $to,
                 Cc       => $cc,
                 Subject  => $subject,
                 Data     => $message
                 );
                 
$msg->send;
print "Email Sent, Bro!\n";

Sending an HTML Email

Since MIME:Lite uses the default sendmail method for sending emails, a HTML email we composed earlier on will look very similar in this case too.

#!/usr/bin/perl
use MIME::Lite;
 
$to = 'mary@mailtrap.io, ann@mailtrap.io, alice@mailtrap.io, kate@mailtrap.io';
$cc = 'john@mailtrap.io';
$from = 'piotr@mailtrap.io';
$subject = 'Apologies';
$message = '<h1>Girls, I\'m also very sorry about all the emails!</h1><p><img src="https://media.giphy.com/media/RWUqVYucDBD4A/giphy.gif" /></p>';

$msg = MIME::Lite->new(
                 From     => $from,
                 To       => $to,
                 Cc       => $cc,                 Subject  => $subject,
                 Data     => $message
                 );
                 
$msg->attr("content-type" => "text/html");         
$msg->send;
print "Email Sent, Bro!\n";

Sending Email with Attachments

One of the key advantages of this module is with how easy it is to add attachments. You can include multiple files in a single email with attach() method.

#!/usr/bin/perl
use MIME::Lite;
 
$to = 'piotr@mailtrap.io';
$cc = 'ann@mailtrap.io, alice@mailtrap.io, kate@mailtrap.io, john@mailtrap.io';
$from = 'mary@mailtrap.io';
$subject = 'Re: Apologies';
$message = '<h1>Will you stop emailing us already???</h1>';

$msg = MIME::Lite->new(
                 From     => $from,
                 To       => $to,
                 Cc       => $cc,
                 Subject  => $subject,                 
                 Type     => 'multipart/mixed'
                 );
                 
# Add your text message.
$msg->attach(  Type     => 'text',  Filename => 'stop-emailing.txt',   
  Data     => $message
);
            
# Specify your file as attachment.
$msg->attach(  Type        => 'image/gif',
  Path        => '/tmp/lawsuit.pdf',
  Filename    => 'lawsuit.pdf',
  Disposition => 'attachment'
);       
$msg->send;
print "Email Sent, Bro!\n";

Sending Emails with MIME::Lite:TT::HTML

There’s also one variation of MIME::Lite that gained quite a momentum. MIME::Lite::TT::HTML looks and works very similar indeed. What makes it different is the ability to use templates instead of hardcoding the content of messages.

This makes it easy to quickly update the body of an email without touching the code base. Whether this means tiny changes or a complete redesign of your emails, it’s much easier done on templates.

If you’re planning to send only simple plain text emails, you’re probably better off with the methods we discussed before. If you need more than that, read on.

Building Templates

Since some email clients don’t display HTML versions of incoming emails (by design or by user’s choice), it’s good to send both plain text and HTML versions of an email. If HTML is supported, the respective version will be displayed. If not, plaintext copy will be loaded.

notice.txt.tt:

Hello [% first_name %],

This is a legal notice of an ongoing case against you, filled by [% client_name %]. I'll be in touch shortly.

Have a pleasant day (it won’t last for long)
Attorney Margaret Smith

notice.html.tt

<p>  Hello [% first_name %],  <br /><br />  This is a *legal notice* of an ongoing case against you, filled by [% client_name %]. I'll be in touch shortly.</p>
<p>  <img src="https://media.giphy.com/media/l0HlxAqevo9mKD3UY/giphy.gif" />  <br /><br />  Have a pleasant day (it won’t last for long)  <br />  Attorney Margaret Smith</p>

Sending a Plaintext/HTML example

Don’t forget to install this module:

cpan -i MIME::Lite::TT::HTML


An example email using both templates will look as follows:

#!/usr/bin/perl

         use strict;
         use warnings;
         use MIME::Lite::TT::HTML;

         my %params;

         $params{first_name} = 'Piotr';
         $params{client_name}  = 'Jane';

         my %options;
         $options{INCLUDE_PATH} = '/path/to/templates';


         my $msg = MIME::Lite::TT::HTML->new(
                    From        =>  'margaret@awesomelawyers.com',
                    To          =>  'piotr@mailtrap.io',
                    Subject     =>  'ICYMI',
                    Template    =>  {
                                        text    =>  'notice.txt.tt',
                                        html    =>  'notice.html.tt',
                                    },
                    TmplOptions =>  \%options,
                    TmplParams  =>  \%params,
         );

         $msg->send;

Adding an Attachment

If you want to include some file, it’s very simple.

#!/usr/bin/perl

         use strict;
         use warnings;
         use MIME::Lite::TT::HTML;

         my %params;

         $params{first_name} = 'Piotr';
         $params{client_name}  = 'Jane';

         my %options;
         $options{INCLUDE_PATH} = '/path/to/templates';

         my $msg = MIME::Lite::TT::HTML->new(
                    From        =>  'margaret@awesomelawyers.com',
                    To          =>  'piotr@mailtrap.io',
                    Subject     =>  'ICYMI',
                    Template    =>  {
                                        text    =>  'notice.txt.tt',
                                        html    =>  'notice.html.tt',
                                    },
                    TmplOptions =>  \%options,
                    TmplParams  =>  \%params,
         );

         $msg->attr("content-type"  => "multipart/mixed");
         $msg->attach(  Type        =>  'application/pdf',
                        Path        =>  '/path/to/prison_map.pdf',
                        Filename    =>  'prison_map.pdf',
                        Disposition =>  'attachment'
         );

         $msg->send;

Notice the five new lines before the send() function that we added. You should pay special attention to the content-type specified in the code. If Margaret was to send a prison plan in a .png file instead of a pdf, she should opt for ‘image/png’ type.

Sending Emails via SMTP

By default, all three methods we covered use localhost for sending emails. But there’s a very good reason behind sending via a reputable SMTP server instead – deliverability

If you’re sending emails to clients and these happen to be some pretty important messages (e.g. order confirmations, password resets), you want to be sure they’re delivered. Locally setup server doesn’t guarantee that. Neither do even the top ESPs, such as SendGrid or Mandrill, but your odds are much better with them.

If you’re planning to send more than occasional status emails, we recommend having a look at some of the more popular providers. Many offer generous free tiers.

Once you pick your provider or decide to set up an SMTP server on your own, adjust the code in your MIME modules and provide the SMTP credentials in send() method:

$msg->send('smtp', "smtp.example.com", AuthUser=>"your_id", AuthPass=>"your_password" );

How Do I Test Emails with Mailtrap?

If your emails will reach external recipients, testing them first would be a solid idea. Of course, you could simply insert your email address into a “To” field and check to see if everything works as expected. However, as your application grows, and different types of emails will be sent, you should probably look for a more sophisticated testing environment.

One such place on the internet is Mailtrap. It’s a fake SMTP server that intercepts your test emails and lets you inspect them in a single inbox. It checks the HTML behind them and gauges each against spam filters. It also lets you BCC your Mailtrap environment on the production emails. So, you’re the first to know when something goes wrong.

Mailtrap is very easy to set up with Perl. When using MIME::Lite or MIME::Lite::HTML::TT, alter the send() function in the following way:

$msg->send('smtp', "smtp.mailtrap.io", Port=>2525, Hello=>"smtp.mailtrap.io", AuthUser=>"your_id", AuthPass=>"your_password" );
print "Email Sent, Bro!\n";

If Net:SMTP is the module of your choice, you’ll also find an example code on the Mailtrap dashboard. 

You can sign up for free at https://mailtrap.io/