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



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.

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


About Jim ...


Click **here**
to try out MailWrench;
a command-line SMTP /
SMTPS (Google Gmail)
mailer for Windows.


Follow me on Twitter

http://twitter.com/lawlessGuy


Recent Posts

A JavaScript REPL for Android Devices

MailSend is Free

My Blog Engine

The October 10th Bug

A Review of Kevin Mitnick's Book Ghost in the Wires

Spellbound by Web Programming

Backlinks to my Blog Posts

Play MP3 Files with Python on Windows


Random Posts

Shrouding CSharp and Java Source Code with AWK

A Command-Line CD Tray Opener

Structuring my Thinking

A TCP Command Line Interface in Rhino JavaScript

BSave and BLoad for the Commodore 64

Internet Protocols and Rhino JavaScript

A GUI for urlx

An Interview with Tom Zimmer: Forth System Developer

Taking Shape

Command-Line Image Format Conversion


Full List of Posts

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


Recent Posts from my Other Blog

Remembering Dr. San Guinary

Why Some Web Sites will go Dark on Jan 18th

SNL Superhero Skit

More Ruby Games

My Ruby Game Challenge Entry

Steal this Bookmarklet

Nerd Toys

Learn New Jargon, You Must

Spot the Wiebe

Tech Magazine Glory Days

Book Review : Paull Allen - Idea Man

A 90's Experiment in Online Systems - The U.S. West CommunityLink Service