An SMTP Server Simulator in Perl
Originally published on: Fri, 08 Jan 2010 23:03:44 +0000
In the late 90's, I wrote a commercial command-line SMTP e-mail utility called MailSend. In order to test the behavior of certain operations, I needed a program that would simulate an SMTP server. This simulator needed to allow me to quickly alter behaviors to generate conditions that customers might be seeing with their SMTP servers.
At the time, I wrote the tool in my utility language of choice: Perl.
smtpsim.pl
# An SMTP server simulator in Perl
#
# License: MIT / X11
# Copyright (c) 2009 by James K. Lawless
# jimbo@radiks.net http://www.radiks.net/~jimbo
# http://www.mailsend-online.com
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
use Socket;
$port = 25;
$sockaddr = 'S n a4 x8';
$authcount=0;
($name, $aliases, $proto) = getprotobyname('tcp');
print "Port = $port\n";
$thisaddr = gethostbyname('localhost');
$this = pack($sockaddr, AF_INET, $port, $thisaddr);
socket(S, AF_INET, SOCK_STREAM, $proto);
bind(S,$this) || die "bind: $!";
listen(S,5) || die "connect: $!";
select(S); $| = 1; select(stdout);
for(;;) {
print "Listening for connection....\n";
($addr = accept(NS,S)) || die $!;
send(NS,"200 okey-dokey\r\n",0);
($af,$port,$inetaddr) = unpack($sockaddr,$addr);
@inetaddr = unpack('C4',$inetaddr);
print "$af $port @inetaddr\n";
$ctr=0;
while ($t=<NS>) {
$ctr++;
if( substr($t,0,4) eq "QUIT") {
last;
}
print $t;
print FIL $t;
if( substr($t,0,1) eq '.') {
send(NS,"200 okey-dokey\r\n",0);
next;
}
$x=substr($t,0,4);
if( ($x eq "EHLO") ||($x eq "HELO") || ($x eq "RCPT") || ($x eq "MAIL") ||
($x eq "RSET") || ($x eq "DATA") || ($x eq "QUIT")) {
send(NS,"200 " . $t . " okey-dokey\r\n",0);
}
}
close(NS);
}
Running the above simulator yields the following output:
Port = 25
Listening for connection....
I then use my MailSend utility to send an email using localhost as the SMTP server address:
C:\j\backup\MAILSEND\755>mailsend -smtp localhost -from jimbo@radiks.net -to jimbo@radiks.net -msg test
The smtpsim.pl console then displays the following conversation:
Port = 25
Listening for connection....
2 2279 127 0 0 1
HELO localhost
MAIL FROM: <jimbo@radiks.net>
RCPT TO: <jimbo@radiks.net>
DATA
To: jimbo@radiks.net
From: jimbo@radiks.net
Mime-Version: 1.0
X-Mail-Agent: MailSend v7.55
test
.
Listening for connection....
The console window for MailSend displays the following;
MailSend v7.55 (Registered version)
attempting connection to localhost
Connection successful.
*** 200 HELO localhost okey-dokey
*** 200 MAIL FROM: <jimbo@radiks.net> okey-dokey
*** 200 RCPT TO: <jimbo@radiks.net> okey-dokey
*** 200 DATA okey-dokey
*** 200 okey-dokey
Send complete!
If I need to try and introduce specific behavior for a given SMTP command, I alter the if statements in the while loop to send back something other than a 200 status code.
The simulator can be used to test any SMTP client.
Unless otherwise noted, all code and text entries are Copyright ©2010 by James K. Lawless
Views expressed in this blog are those of the author and do not necessary reflect those of the author's employer. Views expressed in the comments are those of the responding individual.
Save to StumbleUpon
Digg it
Save to Reddit
Share on Facebook
Share on Twitter
More bookmarks