A perl script sending mails for testing a mail server

This post was written by eli on January 14, 2013
Posted Under: email,Linux,perl,Server admin,Software

Just set up your mail server? Congratulations! Now you should test it. In particular, check if it relays mails to other servers and if the response time is reasonable. Here’s a script for doing the testing. Just edit the arguments to send_mail() to match your setting.

#!/usr/bin/perl
use warnings;
use strict;
use Net::SMTP;

send_mail('127.0.0.1', # Host
 'sender@nowhere.com', #From
 'myself@myhost.com', #to
 'Just a test, please ignore',  #Message body
 "Testing email.\n" # Subject
 );

sub send_mail {
 my ($SMTP_HOST, $from, $to_addr, $body, $subject, $msg) = @_;

 $msg = "MIME-Version: 1.0\n"
 . "From: $from\n"
 . "To: " . ( ref($to_addr) ? join(';', @$to_addr) : $to_addr ) . "\n"
 . "Subject: $subject\n\n"  # Double \n
 . $body;

 #
 # Open a SMTP session
 #
 my $smtp = Net::SMTP->new( $SMTP_HOST,
 'Debug' => 1,       # Change to a 1 to turn on debug messages
 Port => 587,
 );

 die("SMTP ERROR: Unable to open smtp session.\n")
 if(!defined($smtp) || !($smtp));

 die("Failed to set FROM address\n")
 if (! ($smtp->mail( $from ) ) );

 die("Failed to set receipient\n")
 if (! ($smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) ) );

 $smtp->data( $msg );

 $smtp->quit;
}

Two things to note:

The Port assignment marked red above makes an encryption connection with the server. It can be changed to 25, but many servers don’t answer strangers on that port.

July 2024 update: Nowadays, the situation seems to be the opposite. Mail servers that appear in the MX records and owned by Internet actors seem to answer only to port 25, and apparently only small servers answer to 587. Possibly because port 587 is commonly used for outgoing mail by MUAs (mail clients wishing to send an email) and port 25 is used only between servers (MTAs) …?

And if this script is used to talk with a remote server, odds are it won’t work due to authentication issues. If your server runs sendmail, it can be made less picky by making the following temporary changes to allow for testing:

In /etc/mail/sendmail.mc, change confAUTH_OPTIONS from `A’ to `’ (nothing, no authentication required). Also, change

DAEMON_OPTIONS(`Port=submission, Name=MSA, M=Ea')dnl

to

DAEMON_OPTIONS(`Port=submission, Name=MSA')dnl

and then compile the configuration file and restart the server with

# make -C /etc/mail
# service sendmail restart

Needless to say, it’s recommended to return the original settings after the testing is done. Your mail server should have some self-respect.

Anyhow, a typical output should look like this:

Net::SMTP>>> Net::SMTP(2.31)
Net::SMTP>>>   Net::Cmd(2.29)
Net::SMTP>>>     Exporter(5.62)
Net::SMTP>>>   IO::Socket::INET(1.31)
Net::SMTP>>>     IO::Socket(1.30_01)
Net::SMTP>>>       IO::Handle(1.27)
Net::SMTP=GLOB(0x7c9d98)<<< 220 myhost.localdomain ESMTP Sendmail 8.14.4/8.14.4; Mon, 14 Jan 2013 14:03:26 +0200
Net::SMTP=GLOB(0x7c9d98)>>> EHLO localhost.localdomain
Net::SMTP=GLOB(0x7c9d98)<<< 250-myhost.localdomain Hello localhost.localdomain [127.0.0.1], pleased to meet you
Net::SMTP=GLOB(0x7c9d98)<<< 250-ENHANCEDSTATUSCODES
Net::SMTP=GLOB(0x7c9d98)<<< 250-PIPELINING
Net::SMTP=GLOB(0x7c9d98)<<< 250-8BITMIME
Net::SMTP=GLOB(0x7c9d98)<<< 250-SIZE
Net::SMTP=GLOB(0x7c9d98)<<< 250-DSN
Net::SMTP=GLOB(0x7c9d98)<<< 250-ETRN
Net::SMTP=GLOB(0x7c9d98)<<< 250-AUTH DIGEST-MD5 CRAM-MD5 LOGIN PLAIN
Net::SMTP=GLOB(0x7c9d98)<<< 250-DELIVERBY
Net::SMTP=GLOB(0x7c9d98)<<< 250 HELP
Net::SMTP=GLOB(0x7c9d98)>>> MAIL FROM:<sender@nowhere.com>
Net::SMTP=GLOB(0x7c9d98)<<< 250 2.1.0 <sender@nowhere.com>... Sender ok
Net::SMTP=GLOB(0x7c9d98)>>> RCPT TO:<myself@myhost.com>
Net::SMTP=GLOB(0x7c9d98)<<< 250 2.1.5 <myself@myhost.com>... Recipient ok
Net::SMTP=GLOB(0x7c9d98)>>> DATA
Net::SMTP=GLOB(0x7c9d98)<<< 354 Enter mail, end with "." on a line by itself
Net::SMTP=GLOB(0x7c9d98)>>> MIME-Version: 1.0
Net::SMTP=GLOB(0x7c9d98)>>> From: sender@nowhere.com
Net::SMTP=GLOB(0x7c9d98)>>> To: myself@myhost.com
Net::SMTP=GLOB(0x7c9d98)>>> Subject: Testing email.
Net::SMTP=GLOB(0x7c9d98)>>>
Net::SMTP=GLOB(0x7c9d98)>>>
Net::SMTP=GLOB(0x7c9d98)>>> Just a test, please ignore
Net::SMTP=GLOB(0x7c9d98)>>> .
Net::SMTP=GLOB(0x7c9d98)<<< 250 2.0.0 r0EC3Qm3030991 Message accepted for delivery
Net::SMTP=GLOB(0x7c9d98)>>> QUIT
Net::SMTP=GLOB(0x7c9d98)<<< 221 2.0.0 myhost.localdomain closing connection

Reader Comments

Works great and this really helped, so thanks for breaking this down for me…..

Much appreciated

#1 
Written By Keith on April 20th, 2016 @ 15:49

Thanks for sharing, is it possible to scan smtp from file with multi threads ?

#2 
Written By Edvin on April 25th, 2017 @ 20:50

Add a Comment

required, use real name
required, will not be published
optional, your blog address