Jim Lawless' Blog


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

del_icio_us Save to del.icio.us
stumbleupon Save to StumbleUpon
digg Digg it
reddit Save to Reddit
facebook Share on Facebook
twitter Share on Twitter
aolfav More bookmarks



Previous post: Along Came AWK
Next post:Charging by the Byte


Search this Blog (and site)

Search this Site with PicoSearch


Subscribe to this Blog

 Subscribe!


Contact Me

Email: jimbo@radiks.net


Follow me on Twitter

http://twitter.com/lawlessGuy


Recent Posts

Mad Schemes : Learning Lisp via SICP

Auto Save Clipboard Images Redux

Extending SpiderMonkey JavaScript on Windows

Rhino JavaScript to EXE with launch4j

Compiling Rhino JavaScript to Java

Directory Traversal in Rhino JavaScript

Taking Shape

We've Moved!


Popular Posts

A Command-Line MP3 Player for Windows

Auto Save Images from the Clipboard

Java in a Windows EXE with launch4j

An Interview with Tom Zimmer: Forth System Developer

Setting Windows Console Text Colors in C


Random Posts

Preventing Windows Screen-Saver Activation

My Big Shareware Splash

Embedding JavaScript in a Batch File

Mad Schemes : Learning Lisp via SICP

An Interview with the Author of the French Silk Assembler

Scrolling GIF Banners with PerlMagick

A Simple Parser for a Small Command Line Interface

WSH2EXE part 1

Jim Butterfield : The Commodore Guru

A TCP Command Line Interface in Rhino JavaScript


Full List of Posts

http://www.mailsend-online.com/bloglist.htm


Blogroll

MicroISV on a Shoestring
DadHacker
The Bottom Feeder
Writin' That Code!
The Recursive ISV
The Thomsen Blog
Prototypically Speaking
The Reinvigorated Programmer