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. If you don’t like any of these options, you can even build your own module, and you won’t have to spend the next week doing so.
In this article, we 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, but don’t expect excellent delivery rates. In our tests, several 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 using Linux/Unix machines. For Windows and other devices, you’ll need to look at alternative approaches.
To use the `sendmail` service on Ubuntu, you will typically follow these steps to install, configure, and send an email using sendmail. Note that while sendmail is a traditional mail transfer agent, many users opt for alternatives like `Postfix` due to easier configuration and maintenance.
You can check if the sendmail service is working on the system by calling this command. `systemctl status sendmail`
Make sure you configure Sendmail properly and let’s try sending a few sample emails.
Sending a Plaintext message
Here’s a sample code for sending an email with Sendmail:
#!/usr/bin/perl
use strict;
use warnings;
my $to = 'jane@mailtrap.io';
my $from = 'piotr@mailtrap.io';
my $subject = 'w00t it works!';
my $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;
my $result = close(MAIL);
if($result) {
print "Email Sent, Bro!\n";
} else {
print "There was a problem, Bro!\n";
}
What just happened? We configured the address we send from ($from
) and the recipient’s address ($to
). We also specified the subject and the message.
We then opened the Sendmail utility, inserted all these details, and added the message to a sending queue on your local host. If you have a mail server set up, Jane should see our miserable attempt in her inbox in a few seconds.
If you don’t, make sure 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 testing or internal error reporting. However, if you 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
use strict;
use warnings;
my $to = 'jane@mailtrap.io';
my $from = 'piotr@mailtrap.io';
my $subject = 'It\'s me again';
my $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
use strict;
use warnings;
my $to = 'kate@mailtrap.io';
my $from = 'piotr@mailtrap.io';
my $cc = 'mary@mailtrap.io, ann@mailtrap.io, alice@mailtrap.io';
my $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 Mail::Sendmail;
%mail = (
from => 'john@mailtrap.io',
to => 'piotr@mailtrap.io',
subject => 'This is the last warning'
);
$boundary = "====" . time() . "====";
$mail{'smtp'} = 'smtp_server:smth_port;
$mail{'auth'} = {user => "smtp_user", pass => "smtp_pass", method => 'auth_method'};
$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." );
open (F, './complaints.txt') or die "Cannot read file!";
$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="complaints.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="complaints.txt"
$mail{body}
$boundary--
END_OF_BODY
sendmail(%mail) || print "Error: $Mail::Sendmail::error\n";
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 and install it with the following code:
tar xvfz MIME-Lite-3.033.tar.gz
cd MIME-Lite-3.033
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 plain text emails is extremely simple. Here’s an example:
#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'jane@mailtrap.io';
my $cc = 'john@mailtrap.io';
my $from = 'piotr@mailtrap.io';
my $subject = 'Apologies';
my $message = 'Hey, I’m really sorry for the 132 emails I sent you last quarter.';
my $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, an HTML email we composed earlier on will look very similar in this case too.
u#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'mary@mailtrap.io, ann@mailtrap.io, alice@mailtrap.io, kate@mailtrap.io';
my $cc = 'john@mailtrap.io';
my $from = 'piotr@mailtrap.io';
my $subject = 'Apologies';
my $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>
';
my $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 the simplicity of adding attachments. You can include multiple files in a single email with the attach()
method.
#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'piotr@mailtrap.io';
my $cc = 'ann@mailtrap.io, alice@mailtrap.io, kate@mailtrap.io, john@mailtrap.io';
my $from = 'mary@mailtrap.io';
my $subject = 'Re: Apologies';
my $message = '<h1>Will you stop emailing us already???</h1>';
# Add your text message.
$msg->attach(
Type => 'TEXT',
Data => $message
);
# Specify your file as attachment.
$msg->attach(
Type => 'application/pdf',
Path => './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 has gained some momentum. MIME::Lite::TT::HTML looks and works very similarly. 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 the 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, a plain text 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;
print "Email Sent, Bro!\n";
Adding an attachment
If you want to include a 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;
print "Email Sent, Bro!\n";
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 in Perl via SMTP
By default, all three methods we covered use localhost for sending emails. Though localhost is an okay option for personal correspondence, it’s certainly not suitable for bulk sending. It can compromise email deliverability, which means important messages such as order confirmations or password resets may not reach recipients’ inboxes.
And that’s where Mailtrap Sending comes in.
Firstly, Mailtrap allows you to send with an impressive sending throughput of 10,000 emails per second.
It also provides developers with an email infrastructure with high deliverability rates and allows you to control email statistics with helicopter-view dashboards, in-depth analytics, and alerts.
There are also dedicated IPS, auto IP warmups, suppression lists, and other features that are designed to make sure your emails reach your recipients’ inboxes.
Additionally, with Mailtrap, you can dig deeper into email extended history.
Here’s what you need to do to start sending emails from Perl with Mailtrap Email API/SMTP:
- Register and log in to your account;
- Click ‘Sending Domains’ to add and verify your domain. You can find detailed instructions here;
- Once the domain is verified, go to the ‘SMTP/API Settings’ tab
- Choose the stream you’d like to use – Transactional or Bulk (Here we’ll use Transactional)
- Then select ‘SMTP’
- Copy your credentials and go back to your Perl project;
- Adjust the code in your MIME modules and provide SMTP credentials in
send()
method:
$msg->send('smtp', "live.smtp.mailtrap.io", AuthUser=>"your_username", AuthPass=>"your_api_token" );
If you were to use MIME::Lite, the complete code would look like this:
#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'mary@mailtrap.io, ann@mailtrap.io, alice@mailtrap.io, kate@mailtrap.io';
my $cc = 'john@mailtrap.io';
my $from = 'piotr@mailtrap.io';
my $subject = 'Can’t wait to see you';
my $message = '<h1>Girls, I\'m getting out of prison soon!</h1>
<p><img src="https://media.giphy.com/media/RWUqVYucDBD4A/giphy.gif" /></p>
';
my $msg = MIME::Lite->new(
From => $from,
To => $to,
Cc => $cc,
Subject => $subject,
Data => $message,
Encoding => ‘quoted-printable’
);
$msg->attr("content-type" => "text/html");
$msg->send('smtp', "live.smtp.mailtrap.io", AuthUser=>"your_username", AuthPass=>"your_api_token", SSL => 1, Port => 465 );
print "Email Sent, Bro!\n";
Sending emails in Perl using API
Mailtrap also offers an email API with which you can automate your email sending.
First, register an account and verify your email sending domain name. Then, navigate to the SMTP/API Settings tab in the Sending Domains section, where you’ll find your API key/token. As a reminder – make sure you’re using the correct sending stream.
After getting the token credentials and storing them, to start sending via API, all you have to do is copy the following Perl script:
```perl
use strict;
use warnings;
use HTTP::Tiny;
use JSON;
my $url = 'https://send.api.mailtrap.io/api/send';
my $data = {
'from' => {'email' => ‘sender@domain.com'},
'to' => [{'email' => 'receiver@domain.com'}],
'subject' => 'Test Email',
'text' => 'This is a test email using Perl and Mailtrap API!',
};
my $json_payload = encode_json($data);
my $http = HTTP::Tiny->new();
my $response = $http->post($url, {
'headers' => { 'Content-Type' => 'application/json', 'Api-Token' => 'token here'},
'content' => $json_payload
});
if ($response->{success}) {
print "Response: " . $response->{content};
} else {
die "HTTP POST error: " . $response->{status} . " - " . $response->{reason};
}
```
Here’s a step-by-step explanation of the code:
- use HTTP::Tiny; – imports the HTTP::Tiny module, which provides a minimalist HTTP client. This is used to execute the HTTP POST request to the Mailtrap API.
- use JSON; – imports functions to encode and decode JSON. JSON encoding is necessary because the Mailtrap API expects the request payload in JSON format.
- The script sends the POST request using $http->post($url, {…}). The request includes:
- A headers hash reference specifying the `Content-Type` as `application/json ` and providing the Api-Token. The Api-Token is essential for authenticating the request with the Mailtrap API.
- The `content` key with the value of $json_payload, which is the JSON-encoded email data.
Testing emails before sending them in Perl: why and how?
If your emails are addressed to 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 you start sending different types of emails, you should probably look for a more sophisticated testing environment.
One such place on the internet is Mailtrap Email Sandbox. It’s a safe environment to test and debug emails before sending them to inboxes. It captures all the SMTP traffic from staging, making sure that test emails don’t spam users.
Try Mailtrap Email Sandbox for Free
The Email Sandbox checks the HTML/CSS in each email and gauges them against spam filters and blacklists.
Mailtrap also checks your spam score, which, if you keep under 5, will prevent any deliverability issues when you move your app to production. Basically, with Mailtrap, you can make sure your emails land where they’re supposed to, instead of spam folders.
Once you’re happy with the results, it lets you forward the emails to the real addresses manually or automatically.
Mailtrap Email Sandbox is also very easy to set up with Perl. You have two options: use SMTP credentials for any Perl module or copy ready-made code configurations.
SMTP
If you go with the SMTP route, all you have to do is create an account and:
- Navigate to the ‘Sandbox’ tab and press ‘My Inbox’;
- You’ll see the ‘SMTP Settings’ tab. Press ‘Show Credentials’ to reveal the host, port, your username, and password;
- Copy those credentials and paste them into the Perl module you’re using.
Using the code configuration:
Don’t feel like using credentials? You don’t have to—here’s a code configuration you can use instead:
- Navigate to the ‘Sandbox’ tab and press ‘My Inbox’;
- Open the dropdown menu from the ‘Integrations’ tab and choose MIME::Lite or NET::SMTP;
- Modify parameters such as ‘To’ and ‘From’ addresses, as well as the message subject and body.
When using MIME::Lite or MIME::Lite::HTML::TT, alter the send()function in the following way:
$msg->send('smtp', "sandbox.smtp.mailtrap.io", Port=>2525, Hello=>"sandbox.smtp.mailtrap.io", AuthUser=>"your_username", AuthPass=>"your_password" );
print "Email Sent, Bro!\n";
Here’s what a sample code would look like if you were using NET::SMTP module:
#!/usr/bin/perl
use strict;
use Cwd;
use Data::Dumper;
use Net::SMTP;
use File::Slurp;
sub sendMail($$);
use constant DEBUG => 0;
my $startDir = getcwd;
my %email = ( 'smtp' => 'sandbox.smtp.mailtrap.io',
'hello' => 'sandbox.smtp.mailtrap.io',
'user' => 'your_username',
'pass' => 'your_password',
'no_mail' => 0, # Don't send mail. Useful for checking what would be sent...
'debug' => 1, # Print extra smtp feedback.
'from' => 'piotr@mailtrap.io',
'to' => [ 'margaret@awesomelawyers.com' ],
'subject' => 'I may need your help once more' );
my $bodyfile = $ARGV[0];
unless (-f $bodyfile){
die "usage: $0 <file_containing_email_body>";
}
my $mail_body = read_file($bodyfile);
print "sending mail...\n" if(DEBUG);
sendMail(\%email, $mail_body);
exit 0;
# =======================================================
sub sendMail($$){
my $m = shift;
my $out = shift;
my $toList = join ',', @{ $m->{'to'} };
if( $m->{'no_mail'} ){
print "sendMail(no_mail=1): NOT sending\n" . Dumper($m) . "\n" . Dumper($out) . "\n";
return;
}
my $smtp = Net::SMTP->new( $m->{'smtp'}, 'Hello' => $m->{'hello'},
'Debug' => $m->{'debug'}, 'Port' => 2525 );
$smtp->auth( $m->{'user'}, $m->{'pass'} );
$smtp->mail( $m->{'from'} );
$smtp->to( @{ $m->{'to'} } );
$smtp->data();
$smtp->datasend("From: $m->{'from'}\n" );
$smtp->datasend("To: $toList\n" );
$smtp->datasend("Subject: $m->{'subject'}\n" );
$smtp->datasend("\n");
$smtp->datasend( "$out\n" );
$smtp->dataend();
$smtp->quit;
}
API
With Mailtrap API, you can automate your entire testing process, test automated sequences, and have complete control of your infrastructure before sending email.
To integrate Mailtrap API with your application, simply use the following code:
use strict;
use warnings;
use HTTP::Tiny;
use JSON;
my $url = 'https://sandbox.api.mailtrap.io/api/send/inbox-id(integer);
my $data = {
'from' => {'email' => 'sender@domain.com'},
'to' => [{'email' => 'receiver@domain.com'}],
'subject' => 'Test Email',
'text' => 'This is a test email using Perl and Mailtrap API!',
};
my $json_payload = encode_json($data);
# print $json_payload;
my $http = HTTP::Tiny->new();
my $response = $http->post($url, {
'headers' => { 'Content-Type' => 'application/json', 'Api-Token' => 'api-token'},
'content' => $json_payload
});
if ($response->{success}) {
print "Response: " . $response->{content};
} else {
die "HTTP POST error: " . $response->{status} . " - " . $response->{reason};
}
Note: At the end of the API endpoint, you can notice the integer is added which is indicating the inbox of the email to be tested.
Wrapping up
Perl has multiple modules that could be used for sending emails. In this guide, we covered the most common options such as Sendmail, MIME::Lite, and MIME::Lite::TT::HTML. We also discussed why it’s a good idea to send emails from Perl with a third-party SMTP/API service, such as Mailtrap Email API/SMTP.
It’s important to test your emails before sending them to users with a safe environment such as Mailtrap Email Sandbox.
If there’s any other topic you’d like us to cover, let us know on our social media channels.
Comments
1 replies