Skip to content

Perl Sending Email

Sending email from a Perl script is a common task for notifications, reports, or application alerts. Modern Perl offers several modules on CPAN for robust and flexible email handling. While direct use of system utilities like sendmail is possible on Unix-like systems, using modules is generally preferred for portability, features, and ease of use.

Using System sendmail Utility (Unix/Linux)

Section titled “Using System sendmail Utility (Unix/Linux)”

On Unix-like systems with sendmail (or a compatible Mail Transfer Agent like Postfix or Exim) configured, you can pipe email content to it. This method is simple for basic emails but lacks advanced features and portability.

Sending a Plain Text Message with sendmail

Section titled “Sending a Plain Text Message with sendmail”
#!/usr/bin/perl
use strict;
use warnings;
my $to = 'recipient@example.com';
my $from = 'sender@example.com';
my $subject = 'Test Email from Perl (sendmail)';
my $message_body = "This is a test email sent by a Perl script using sendmail.
Regards,
Perl Script";
# Adjust path to sendmail if necessary
my $sendmail_path = "/usr/sbin/sendmail";
unless (open(MAIL, "|- ", "$sendmail_path -t -oi")) {
die "Could not open pipe to sendmail: $!";
}
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n";
print MAIL "\n"; # Blank line separates headers from body
print MAIL $message_body;
unless (close(MAIL)) {
die "Sendmail command failed: $? $!"; # $? for exit status
}
print "Email sent successfully via sendmail (hopefully!)\n";

Note: The -t option tells sendmail to read recipients from the headers. -oi prevents treating a line with a single dot as end-of-message. This method relies on a correctly configured local MTA.

Section titled “Using Perl Modules for Email (Recommended)”

Using CPAN modules is the standard and recommended way to handle email in Perl. Modules like Email::Stuffer, Email::Sender, and the older MIME::Lite provide comprehensive features.

To install modules, you typically use cpanm (App::cpanminus):

cpanm Module::Name # e.g., cpanm Email::Stuffer

Using MIME::Lite Module (Older, but still functional)

Section titled “Using MIME::Lite Module (Older, but still functional)”

MIME::Lite is a long-standing module for creating and sending MIME messages. While newer modules offer more modern APIs, MIME::Lite is relatively simple for basic tasks. For new projects, consider Email::Stuffer or Email::Sender combined with Email::MIME::Creator.

Sending a Plain Text Message with MIME::Lite:

#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'recipient@example.com';
my $from = 'sender@example.com';
my $subject = 'Test Email from Perl (MIME::Lite)';
my $message_body = "This is a test email sent via MIME::Lite.";
try {
my $msg = MIME::Lite->new(
From => $from,
To => $to,
Subject => $subject,
Data => $message_body,
Type => 'text/plain' # Explicitly set type
);
# By default, MIME::Lite tries to use sendmail.
# For other transport methods, see send_by_smtp below.
$msg->send;
print "Email sent successfully via MIME::Lite!\n";
}
catch {
warn "Failed to send email: $_\n";
};

Sending an HTML Message with MIME::Lite:

#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'recipient@example.com';
my $from = 'sender@example.com';
my $subject = 'HTML Test Email from Perl (MIME::Lite)';
my $html_body = <<'END_HTML';
<h1>Hello from Perl!</h1>
<p>This is an **HTML** email sent using `MIME::Lite`.</p>
<p><a href="https://www.perl.org">Visit Perl.org</a></p>
END_HTML
try {
my $msg = MIME::Lite->new(
From => $from,
To => $to,
Subject => $subject,
Type => 'text/html', # Set content type to HTML
Data => $html_body
);
$msg->send;
print "HTML Email sent successfully via MIME::Lite!\n";
}
catch {
warn "Failed to send HTML email: $_\n";
};

Sending an Email with Attachments using MIME::Lite:

#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'recipient@example.com';
my $from = 'sender@example.com';
my $subject = 'Email with Attachment (MIME::Lite)';
my $text_body = "Please find the attached report.";
my $attachment_path = './report.txt'; # Create a dummy report.txt for testing
# Create a dummy attachment file for testing
open my $fh, '>', $attachment_path or die "Cannot create dummy attachment: $!";
print $fh "This is a test report.\nLine 2 of report.\n";
close $fh;
try {
my $msg = MIME::Lite->new(
From => $from,
To => $to,
Subject => $subject,
Type => 'multipart/mixed' # For messages with attachments
);
# Attach the text part
$msg->attach(
Type => 'text/plain',
Data => $text_body
);
# Attach the file
$msg->attach(
Type => 'text/plain', # Or application/octet-stream, etc.
Path => $attachment_path,
Filename => 'report_from_perl.txt', # Name for the attachment
Disposition => 'attachment'
);
$msg->send;
print "Email with attachment sent successfully via MIME::Lite!\n";
}
catch {
warn "Failed to send email with attachment: $_\n";
}
unlink $attachment_path; # Clean up dummy file

If your machine isn’t configured to send mail directly (e.g., no local sendmail), or you need to use a specific SMTP server (like Gmail, SendGrid, etc.), you can configure MIME::Lite to send via SMTP. This usually requires Net::SMTP to be installed.

#!/usr/bin/perl
use strict;
use warnings;
use MIME::Lite;
my $to = 'recipient@example.com';
my $from = 'sender@example.com'; # Often needs to be a valid address on the SMTP server
my $subject = 'SMTP Test from MIME::Lite';
my $body = 'This email was sent via an external SMTP server.';
my $smtp_server = 'smtp.example.com';
my $smtp_user = 'your_username'; # Optional, if authentication is needed
my $smtp_pass = 'your_password'; # Optional
try {
my $msg = MIME::Lite->new(
From => $from,
To => $to,
Subject => $subject,
Data => $body,
Type => 'text/plain'
);
# Option 1: Set global send method for MIME::Lite
# MIME::Lite->send('smtp', $smtp_server, AuthUser => $smtp_user, AuthPass => $smtp_pass, Debug => 1);
# $msg->send();
# Option 2: Use send_by_smtp (or send_via_smtp) on the message object
# This requires Net::SMTP or similar to be available.
$msg->send_by_smtp($smtp_server,
AuthUser => $smtp_user,
AuthPass => $smtp_pass,
Port => 587, # Common port for SMTP with STARTTLS
Hello => 'my.hostname.com', # Optional HELO/EHLO domain
# SSL => 'starttls', # For STARTTLS, often requires Net::SMTP::TLS::ButMaintained or IO::Socket::SSL
# SSL => 1, # For SMTPS (SMTP over SSL directly on port 465)
Debug => 1 # Enable debugging output from Net::SMTP
) or die "SMTP sending failed: " . MIME::Lite->errmsg;
print "Email sent successfully via SMTP!\n";
}
catch {
warn "Failed to send email via SMTP: $_\n";
if (MIME::Lite->errmsg) {
warn "MIME::Lite error: " . MIME::Lite->errmsg . "\n";
}
};

For SMTP, especially with authentication and SSL/TLS, using more modern modules like Email::Sender::Transport::SMTP::TLS (part of the Email::Sender ecosystem) is highly recommended as they handle these complexities more robustly. MIME::Lite’s direct SMTP support can be tricky with modern security requirements.

Modern Alternatives: Email::Stuffer or Email::Sender

Section titled “Modern Alternatives: Email::Stuffer or Email::Sender”

For new Perl projects, consider these more contemporary modules:

  • Email::Stuffer: A popular choice for its simple, fluent interface for creating and sending emails, including HTML, text parts, and attachments. It often uses Email::Sender underneath.
  • Email::Sender: A flexible system for sending email messages, with various transports (SMTP, sendmail, etc.) and good support for modern SMTP features like SSL/TLS and authentication.

Example with Email::Stuffer (conceptual):

#!/usr/bin/perl
use strict;
use warnings;
use Email::Stuffer;
# Conceptual example - details depend on your SMTP setup
my $email = Email::Stuffer->from('sender@example.com')
->to('recipient@example.com')
->subject('Modern Perl Email Test')
->text_body('Hello from Email::Stuffer!')
->html_body('<h1>Hello from Email::Stuffer!</h1>')
->attach_file('./report.pdf');
# To send via SMTP, you might need to configure transport or use Email::Sender directly
# $email->send; # Default send might use sendmail
try {
# Example of sending via Email::Sender with specific transport:
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP;
my $transport = Email::Sender::Transport::SMTP->new({
host => 'smtp.example.com',
port => 587,
# ssl => 'starttls', # or true for SMTPS on port 465
# sasl_username => 'user',
# sasl_password => 'pass',
});
sendmail($email->as_email_mime, { transport => $transport });
print "Email sent with Email::Stuffer via SMTP!\n";
}
catch {
warn "Failed to send email with Email::Stuffer: $_\n";
};

Always consult the documentation for the specific email module you choose, as configuration for SMTP servers, authentication, and encryption can vary.