Archive for the ‘Programming’ Category

Ubuntu Server + Fluxbox on Mac OSX using VirtualBox

Sunday, March 31st, 2013

I like Mac OSX as a general computing environment, but I prefer Debian (and more recently Ubuntu) for development.

Instead of running my Mac in dual-boot mode, I tried using VirtualBox to run Ubuntu Desktop.

Unfortunately, the virtual image was unusable: even at two gigabytes of memory (the most allowed by the vm) it was painfully slow, and using the dash was basically impossible.

But since my development environment consists mostly of ROXTerm and emacs, I wanted to see how Ubuntu Server plus a lightweight window manager such as Fluxbox would work instead.

Fluxbox running like a champ on Ubuntu Server in VirtualBox

Fluxbox running like a champ on Ubuntu Server in VirtualBox

It’s been terrific so far, and the setup was simple:

  1. After downloading the Ubuntu Server iso file, I created a new virtual image and used the iso as the base media
  2. Once installed, I followed the instructions for setting up Fluxbox without a login manager:
    sudo apt-get install xorg fluxbox fluxconf
  3. Then, I started Fluxbox for the first time:
    startx
  4. For the Guest Additions installation, I installed these packages first:
    apt-get install dkms build-essential linux-headers-generic

    And then requested the guest additions from the VirtualBox menu: Devices -> Install Guest Additions which “loads” the guest additions virtual disk. Under gnome or kde the disk gets mounted automatically, but in Fluxbox I had to mount it myself before running the install script:

    sudo mount /dev/dvd /media/cdrom
    cd /media/cdrom
    sudo sh ./VBoxLinuxAdditions.run

State machines in Go (#golang)

Sunday, February 10th, 2013

I’ve been rewriting critical server components that were originally written in Python to use Go instead. Unlike Python, which is interpreted and uses a global lock because the interpreter is not thread-safe, Go has built-in support for concurrency, and is statically compiled.

One of the first things I tackled was implementing a state machine. The Python version was based on this article by David Mertz.

Mertz uses an object oriented approach, defining a class with both data and methods. His code, syntax aside, will be familiar to anyone who has worked with objects in C++, C#, and Java.

Go, however, does not provide a mechanism for coupling methods to specific data structures. Instead, Go allows you to associate methods with data structures, so that any method can be applied to any struct.

It’s a model which is closer to what Alan Kay meant when he defined the term object oriented in the first place.

With that in mind, here’s how I originally wrote the state machine class as a Go struct:

type Machine struct {
    Handlers   map[string]func(interface{}) (string, interface{})
    StartState string
    EndStates  map[string]bool
}

Just as in Mertz’s definition, Handlers is a map whose keys are name strings, and whose values are functions which accept a “cargo” value, and return a next state name string, along with the updated cargo value.

Go treats functions as first-class objects, so storing and passing them from state to state works exactly as it does in Python.

The only change I made was in the end state list: whereas Mertz used a list of strings, I used a map, since there’s no fast equivalent of detecting presence in a list (in Go, the only way to do it would be to iterate through the entire list of strings until or unless a match is found).

Since the handler function signature is a little unwieldy, I created a user-defined function type for it:

type Handler func(interface{}) (string, interface{})

type Machine struct {
    Handlers   map[string]Handler
    StartState string
    EndStates  map[string]bool
}

All that leaves is the definition of the methods associated with the Machine struct.

The first two provide a way to define which handler function is associated with which name string, and which name strings constitute end states:

func (machine *Machine) AddState(handlerName string, handlerFn Handler) {
    machine.Handlers[handlerName] = handlerFn
}

func (machine *Machine) AddEndState(endState string) {
    machine.EndStates[endState] = true
}

It’s worth noting that since EndStates is a map (or a list, in Mertz’s original), it’s possible to have more than one state terminate processing.

The final method is the one which executes the state machine, by applying the appropriate handler function to the cargo value, stopping when an end state has been reached.

Since the set of functions are stored as first-class objects in a map, looking them up based on their names and invoking them is trivial:

func (machine *Machine) Execute(cargo interface{}) {
    if handler, present := machine.Handlers[machine.StartState]; present {
        for {
            nextState, nextCargo := handler(cargo)
            _, finished := machine.EndStates[nextState]
            if finished {
                break
            } else {
                handler, present = machine.Handlers[nextState]
                cargo = nextCargo
            }
        }
    }
}

The only possible fly in the ointment is Go’s strong typing, since the type of the cargo value in the handler function signature needs to be specified.

By using the generic interface{} as the type, however, all the handler functions need to do is invoke a type assertion on the incoming cargo value, and they can handle any data (the test example uses a float for the cargo, but it can be any data type, even user-defined structs).

The complete state machine is available as a Go package.

Simple Social Media “Share” Buttons

Tuesday, December 18th, 2012

I’ve recently included social media “share” buttons both here on this site, and at macaronics.com (whether or not they serve any useful purpose is another question entirely).

A problem with implementing them, though, is that each site wants you to include a boatload of javascript along with the button images, and you also have to set the button within an iframe or other weird DOM construct foreign to your page layout.

Getting each of the buttons to line up in a simple row is so tricky, in fact, that a bunch of third party services have cropped up to do the work for you.

But if you don’t care about having the current number of “likes” or “shares” displayed, there is a simpler way.

My technique is based on this approach by Steve Wortham and reddit’s method for using javascript within the link to identify the window.location and use that to build the share link dynamically.

For the button images, I used Fatcow’s Free Icons for Facebook, Twitter, LinkedIn, and Google Plus.

Reddit and Pinterest both provide button icons (though for Pinterest I had to download the png logo file and scale it down to the same size as the others).

Except for reddit, none of the sites offered hosting (without involving all the extraneous javascript includes I didn’t want in the first place), so I used Imgur.

You can see the results here:

How to extract just the text from html page articles

Saturday, October 27th, 2012

One of the reasons I keep going back to Python is because of the lxml library.

Not only is it terrific in terms of handling xml, it can do wonders with html of all flavors, even badly-formed and specification-invalid html data.

A common task I have these days is to grab the text from an html page or article (e.g., in curating content for Macaronics).

As this gist shows, lxml makes this dead simple, using xpath and the “descendant-or-self::” axis selector.

The only real work is understanding the page structure and creating the correct xpath expression for each site (the readability algorithm is essentially a collection of these rules), and monitoring their changes over time so that the xpath expression can be updated accordingly.

Another bonus is that it works with foreign language sites, too, provided the parser is passed the same encoding as defined in the target page’s Content-Type meta tag.

Here’s an example of grabbing the text from a web article by Facta, a Japanese business magazine, and saving it as a text file, so I can add it to the list of articles in Macaronics:

>>> import urllib, text_grabber
>>> data=urllib.urlopen('http://facta.co.jp/article/201211043-print.html').read()
>>> t=text_grabber.facta_print(data)
>>> import codecs
>>> f=codecs.open('facta-201211043-print.txt', 'w', 'utf-8'); f.write(t); f.close()

Go (#golang) and MongoDB using mgo

Sunday, October 14th, 2012

After working in node.js last year, I’ve switched to learning Go instead, and I wanted to reprise my "Node.js and MongoDB: A Simple Example" post in Go.

Of all the Go drivers available for mongoDB, mgo is the most advanced and well-maintained.

The example on the mgo main page is easy to understand:

  1. Create a struct which matches the BSON documents in the database collection you want to access
  2. Obtain a session using the Dial function, which creates a connection object
  3. Use the connection object to access a particular collection in your database:
    • Searches load documents from the database into the struct
    • Inserts and updates take data defined in a struct and create/update documents in the database

So for a collection named “Person”, where a typical document looks like this:

{
        "_id" : ObjectId("502fbbd6fec1300be858767e"),
        "lastName" : "Seba",
        "firstName" : "Jun",
        "inserted" : ISODate("2012-08-18T15:59:18.646Z")
}

The corresponding Go struct would be:

type Person struct {
    Id         bson.ObjectId   "_id,omitempty"
    FirstName  string          "firstName"
    MiddleName string          "middleName,omitempty"
    LastName   string          "lastName"
    Inserted   time.Time       "inserted"
}

It turns out the third field in each line, the string literal tag which is normally optional in a Go struct, is required here, because mgo won’t find those fields in the database otherwise.

It’s also possible to convert database results directly into json, which is useful for creating API services that output json.

In that case, it’s necessary to define both a bson tag and a json one, surrounded by backticks:

type Person struct {
    Id         bson.ObjectId   `bson:"_id,omitempty" json:"-"`
    FirstName  string          `bson:"firstName" json:"firstName"`
    MiddleName string          `bson:"middleName,omitempty" json:"middleName,omitempty"`
    LastName   string          `bson:"lastName" json:"lastName"`
    Inserted   time.Time       `bson:"inserted" json:"-"`
}

The json tag follows the conventions of the built-in Go json package: “-” means ignore, “omitempty” will exclude the field if its value is empty, etc.

So far so good.

But accessing different collections in a database means that for each one: it has its own struct defined, it has its own connection with the collection name specified, and an access function (Find, Insert, Remove, etc.) which marshals/unmarshals those results.

And the last step in particular can lead to a lot of code repetition.

Inspired by Alexander Luya’s post on mgo-users, I’ve created a framework that allows for multiple access functions with a minimum of repetiton.

First, this function, which creates or clones the call to Dial() as needed (this is very similar to what Alex posted):

var (
    mgoSession     *mgo.Session
    databaseName = "myDB"
)

func getSession () *mgo.Session {
    if mgoSession == nil {
        var err error
        mgoSession, err = mgo.Dial("localhost")
        if err != nil {
             panic(err) // no, not really
        }
    }
    return mgoSession.Clone()
}

Next, a higher-order function which takes a collection name and an access function prepared to act on that collection:

func withCollection(collection string, s func(*mgo.Collection) error) error {
    session := getSession()
    defer session.Close()
    c := session.DB(databaseName).C(collection)
    return s(c)
}

The withCollection() function takes the name of the collection, along with a function that expects the connection object to that collection, and can execute access functions on it.

Here’s how the “Person” collection can be searched, using the withCollection() function:

func SearchPerson (q interface{}, skip int, limit int) (searchResults []Person, searchErr string) {
    searchErr     = ""
    searchResults = []Person{}
    query := func(c *mgo.Collection) error {
        fn := c.Find(q).Skip(skip).Limit(limit).All(&searchResults)
        if limit < 0 {
            fn = c.Find(q).Skip(skip).All(&searchResults)
        }
        return fn
    }
    search := func() error {
        return withCollection("person", query)
    }
    err := search()
    if err != nil {
        searchErr = "Database Error"
    }
    return
}

The skip and limit parameters are optional in that if skip is set to zero, it is effectively asking for all the results, and, similarly, if limit is set to an integer less than zero, it is ignored in the query that gets invoked inside the withCollection() function.

So with that framework in place, making a variety of different queries on the "Person" collection reduces to writing simple (often one-line) BSON queries, as in the following examples.

(1) Get all people whose last name beings with a particular string:

func GetPersonByLastName (lastName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{"lastName": bson.RegEx{"^"+lastName, "i"}}, skip, limit)
    return
}

(2) Get all people whose last name is exactly the given string:

func GetPersonByExactLastName (lastName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{"lastName": lastName}, skip, limit)
    return
}

(3) Find people whose first and last names being with the particular strings:

func GetPersonByFullName (lastName string, firstName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{
        "lastName": bson.RegEx{"^"+lastName, "i"},
        "firstName": bson.RegEx{"^"+firstName, "i"}}, skip, limit)
    return
}

(4) Find people whose first and last names match with first and last names exactly:

func GetPersonByExactFullName (lastName string, firstName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{"lastName": lastName, "firstName": firstName}, skip, limit)
    return
}

et. cetera.

As far as code repetition goes, however, this framework is not that efficient in that each collection requires its own Search[Collection]() function, where the only difference among the different functions is the type of the searchResults variable.

It would be tempting to write something like this:

func Search (collectionName string, q interface{}, skip int, limit int) (searchResults []interface{}, searchErr string) {
    searchErr = ""
    query := func(c *mgo.Collection) error {
        fn := c.Find(q).Skip(skip).Limit(limit).All(&searchResults)
        if limit < 0 {
            fn = c.Find(q).Skip(skip).All(&searchResults)
        }
        return fn
    }
    search := func() error {
        return withCollection(collectionName, query)
    }
    err := search()
    if err != nil {
        searchErr = "Database Error"
    }
    return
}

Except this is where Go's strong typing gets in the way: "there's no magic that would turn an interface{} into a Person", and so each Search[Collection]() function has to be written separately.

The right way to use setInterval() and setTimeout() in Javascript

Saturday, July 14th, 2012

Most of the tutorials and examples for using setInterval() and setTimeout() describe the first parameter (which represents the function to execute) as a string, like this,

setTimeout("count()",1000);

Even the normally reliable O’Reilly men do it this way, too. Stephen Chapman is one of the few who gets it right.

While this technique works, it has two problems.

First, if the function you want to pass has parameters of its own, escaping and formatting them into a string properly is a mess, even in a simple example like this one,

setTimeout('window.alert(\'Hello!\')', 2000);

and it can get even more complicated.

Second, this technique uses eval() to execute the function, which is evil, and to be avoided.1

Using a javascript closure is a better approach:

setTimeout(function () {
    // do some stuff here
  }, 1000);

This makes sending parameters to the underlying function easy,

setTimeout(function (a, b, c) {
    // do some stuff here
  }, 1000);

and it avoids using eval() entirely.

[1] While not exactly related, there’s more in this vein at the hilarious (the (axis-of (eval))) blog, which I found on news.lispnyc.org recently.

Goodbye Java

Sunday, July 1st, 2012

It has been several years since I touched any Java code, and since it’s unlikely that I’ll work in the new Cobol again, I donated all my ancient reference volumes to the local used bookstore today.

Using Microsoft’s Translator API with Python

Monday, May 7th, 2012

Before Macaronics, I experimented with automated machine translation.

Microsoft provides a Translator API which performs machine translation on any natural language text.

Unlike Google’s paid Translation API, Microsoft offers a free tier in theirs, for up to 2 million characters per month.

I found the signup somewhat confusing, though, since I had to create more than one account and register for a couple of different services:

  1. I had to register for a Windows Live ID
  2. While logged in with my Live ID, I needed to create an account at the Azure Data Market
  3. Next, I had to go to the Microsoft Translator Data Service and pick a plan (I chose the free, 2 million characters per month option)
  4. Finally, I had to register an Azure Application (since I was testing, I didn’t want to use a public url, and fortunately that form accepted ‘localhost’, though it insisted on my using ‘https’ in the definition)

The last form, i.e., the Azure Application registration, provides two critical fields for API access:

  • Client ID — this is any old string I want to use as an identifier (i.e., I choose it)
  • Client Secret — this is provided by the form and cannot be changed

With all the registrations out of the way, it was time to try a few translations.

The technical docs were well-written, but since there was nothing for Python, I’ve included an example for accessing the HTTP Interface.

My code is based on Doug Hellmann’s article on urllib2, enhanced with Michael Foord’s examples for error-handling urllib2 requests.

Here’s a simple usage example from Japanese to English, in the Python REPL:

>>> import msmt
>>> token = msmt.get_access_token(MY_CLIENT_ID, MY_CLIENT_SECRET)
>>> msmt.translate(token, 'これはペンです', 'en', 'ja')
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">This is a pen</string>

The API returns XML, so a final processing step for a real program would be to use something like lxml to parse out the translation result.

Here’s a snippet for getting just the translated result out of the XML object returned by the API.

In the case of the example above, this is just the classic1 phrase:

This is a pen

[1] It’s classic in that “This is a pen” is the first English sentence Japanese students learn in school (or so I’m told)

A quick guide to DIY animated videos

Friday, December 9th, 2011

Now that TeamWork.io is out in public beta, I wanted to see how difficult it would be to make an intro video, similar to what Google did for its Voice service.

The idea is based on the observation that most people don’t read web pages and would rather watch a video than skim even a brief description.

So with no background in video animation (and no cash to pay anyone to do it for me), I set out to see how far I could get on my own, using free software tools.

I wrote a script consisting of a few frames of stop-motion animation, which I thought would be the simplest to do.

The script starts with someone planning a project, surrounded by a few gantt charts and similar project management paraphernalia. Soon, though, the various charts and forms he needs to process multiply until he’s overwhelmed, and the screen fades to black.

From out of the darkness, a bright light emerges, and the TeamWork.io logo emerges.

That’s just part one. The next step would be to explain how it works, but part one was enough on its own to keep me busy for a while.

Fortunately, there are several free tools available for this kind of production.

Free as in Beer

I started with GIMP, the GNU community’s answer to PhotoShop.

GIMP let me create all the images I needed for part one: the charts and forms smothering our hero are easily done incrementally, by just adding more junk on top and saving each edit as a separate file.

Going from dark to light was also fairly simple, since GIMP has a nice selection of effects filters, one of which, Supernova, let me create a small sunburst in the middle of the black field, then expand it slowly, until the field was white.

Looking back at the first draft, I see that I rushed it a bit too much, but that is a problem with stop-motion: updating changes frame-by-frame is tedious, and there’s always the risk of jumping ahead too much in any given snapshot.

Next, I used Pencil to put the individual frames together with sound and create a single movie file.

Pencil is capable of exporting to QuickTime’s .mov format at a default 851×715 screen resolution, so to keep things simple, I made all my GIMP images 851 pixels wide by 715 pixels tall.

It’s not an ideal aspect ratio for YouTube, though, and I noticed black filler bands on both sides after uploading, but it doesn’t get in the way of comprehending the video.

Pencil also let me add a soundtrack and preview the entire composition of moving frames and sound, but somewhat annoyingly, it didn’t export with sound.

This is a long-time bug, apparently, but I was able to get around it using MEncoder (more on that later).

Finally, I used the speech synthesizer built in to Mac OSX to produce the voice-over.

Say, a free tool for capturing the Mac’s Text-to-Speech output as a file, was invaluable for this task.

Say produces .aiff format sound files, which can be imported as-is into Pencil.

As nice as it is to write a script and have it turned into speech immediately, the sound of a computer-generated voice-over is less than ideal.

“Alex”, by far the best-sounding of the synthesized voices, still came out clunky and awkward.

It seems for the final video I need to bite the bullet and use a real human voice.

The Final Draft Cut

Once I was happy with the sequence of still frames in Pencil, and I made sure the sound synched (more or less) with the video, I created a .mov file of the project.

I could play the .mov file in QuickTime, but, as noted earlier, there was no sound.

That’s where MEncoder comes in, since it’s able to add a sound layer to any video file, using a single command line instruction:

$ mencoder pencil-output.mov -o final.avi \
  -ovc copy -oac copy -audiofile sound.mp3

The only hitch is that it didn’t work with my .aiff file, so I had to convert it to .mp3 format first.

Fortunately, ffmpeg makes this easy:

$ ffmpeg -i sound.aiff -f mp3 -ab 192 \
  -ar 44100 sound.mp3

Here’s the first draft in all its (10 seconds of) glory:

Re-creating Mailinator in Python

Friday, November 11th, 2011

Update: February 21, 2012

I’ve extended this concept into a framework for creating an intelligent email-based agent server, whereby email sent to designated inboxes get dynamic, or custom replies.

It’s the same logic used by the TeamWork.io web service and I’ve decided to open source it on github: https://github.com/dpapathanasiou/intelligent-smtp-responder


Paul Tyma, the creator of Mailinator, once wrote about its architecture. He said that after starting with sendmail, he found it necessary to write his own SMTP server from scratch.

While he never released the Java source code of his server, I wanted to see if I could re-create it using Python, since I also wanted to understand how state machines work in that language.

The Basic Server

To start, I needed some code that would listen on a specific port, and read and respond to clients.

Python’s SocketServer module makes this simple.

Here, in a few lines, is a multi-threaded TCP server that listens on port 8888 of the local machine and echoes back what a connected client sends to it:

#!/usr/bin/python
import SocketServer
cr_lf = "\r\n"
class SMTPRequestHandler (SocketServer.StreamRequestHandler):
    def handle (self):
        try:
            while 1:
                client_msg = self.rfile.readline()
                self.wfile.write(client_msg.rstrip()+cr_lf) # a simple echo
        except Exception, e:
            print e
# server hostname and port to listen on
server_config = ('localhost', 8888) 
if __name__ == '__main__':
    tcpserver = SocketServer.ThreadingTCPServer(server_config, SMTPRequestHandler) 
    tcpserver.serve_forever() 

Start it from a command line prompt (if the port number you choose is less than 1025, then you need to do this as root):

$ python server.py

And test it using telnet:

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
This is an echo
This is an echo
Ok, I get it
Ok, I get it
What next?
What next?

Handling SMTP

Now I needed to be able to understand and reply to SMTP requests. The protocol is fairly simple, with only a handful of commands.

Each command consists of four letters, which appear at the start of the stream sent by the client, and terminated with “\r\n”.

SMTP commands

Tyma did not, however, implement the full list of SMTP commands, since RSET (Reset), VRFY (Verify), NOOP (No operation), and others are used by spammers to abuse or even take over a server, and are rarely required by legitimate email clients.

The server needs to be able to handle the basic interaction, so HELO (Hello) / EHLO (Extended Hello), MAIL (Mail from), RCPT TO (Recipient To), and DATA all need to be supported.

At first glance, it’s tempting to try to implement it like this:

class SMTPRequestHandler (SocketServer.StreamRequestHandler):
    def handle (self):
        try:
            data = {}
            while 1:
                client_msg = self.rfile.readline()
                if client_msg.startswith('MAIL FROM:'):
                    data['sender'] = get_email_address(client_msg)
                elif client_msg.startswith('RCPT TO:'):
                    data['recipient'] = = get_email_address(client_msg)
                ...
                elif client_msg.startswith('QUIT'):
                    break
        except Exception, e:
            print e

Where get_email_address() is defined as, for example, something like this:

def get_email_address (s):
    """Parse out the first email address found in the string and return it"""
    for token in s.split():
        if token.find('@') > -1:
            # token will be in the form:
            # 'FROM:' or 'TO:'
            # and with or without the <>
            for email_part in token.split(':'): 
                if email_part.find('@') > -1:
                    return email_part.strip('<>')

But this gets messy in a hurry. While some commands fit within the neat single-line /^CMND rest of data\r\n/ pattern, others do not.

RCPT, for example, can be repeated multiple times, and once DATA is seen, every subsequent line must be collected until the final /^\.$/ appears.

State Machines to the rescue

A state machine provides a much better way of handling SMTP requests. In his excellent article, David Mertz defines a state machine as:

a directed graph, consisting of a set of nodes and a corresponding set of transition functions. The machine “runs” by responding to a series of events. Each event is in the domain of the transition function belonging to the “current” node, where the function’s range is a subset of the nodes. The function returns the “next” (perhaps the same) node. At least one of these nodes must be an end-state. When an end-state is reached, the machine stops.

And that corresponds exactly to what happens when a client interacts with an SMTP server:

SMTP State Diagram

Brass Tacks

Creating a state machine in Python is simple, since Python allows you to pass functions as higher-order objects. The statemachine.py implementation in Mertz’s article was done in just a few lines of code.

To handle each SMTP node, I defined a series of functions, one for each server response or command.

Here are the function prototypes, where the cargo parameter is a tuple, containing both the stream from/to requests are read and responses written, and a dict of data collected from the request:

def greeting (cargo):
def helo (cargo):
def mail (cargo):
def rcpt (cargo):
def data (cargo):
def process (cargo):

The state machine is defined within the SMTPRequestHandler class like this:

class SMTPRequestHandler (SocketServer.StreamRequestHandler):
    def handle (self):
        try:
            m = StateMachine()
            m.add_state('greeting', greeting)
            m.add_state('helo', helo)
            m.add_state('mail', mail)
            m.add_state('rcpt', rcpt)
            m.add_state('data', data)
            m.add_state('process', process)
            m.add_state('done', None, end_state=1)
            m.set_start('greeting')
            m.run((self, {}))
        except Exception, e:
            print e

So that each function knows how to recognize its assigned command, I defined and compiled these regular expressions. These are created as globals, since it’s more efficient to initiate them once, and have each subsequent method call use the already-existing version.

import re
helo_pattern = re.compile('^HELO', re.IGNORECASE)
ehlo_pattern = re.compile('^EHLO', re.IGNORECASE)
mail_pattern = re.compile('^MAIL', re.IGNORECASE)
rcpt_pattern = re.compile('^RCPT', re.IGNORECASE)
data_pattern = re.compile('^DATA', re.IGNORECASE)
end_pattern = re.compile('^.$')

The greeting() function, which begins the interaction with the client, sends a simple message and passes control to the helo() function. It looks like this:

def greeting (cargo):
    stream = cargo[0]
    stream.wfile.write('220 localhost SMTP'+cr_lf)
    return ('helo', cargo)

Later in the sequence, the mail() function, which is the first node from which data is collected (in this case, the email address of the sender), is the first to save information in the cargo’s dict. It looks like this:

def mail (cargo):
    stream = cargo[0]
    client_msg = stream.rfile.readline()
    if mail_pattern.search(client_msg):
        sender = get_email_address(client_msg)
        if sender is None:
            stream.wfile.write(bad_request+cr_lf)
            return ('done', cargo)
        else:
            email_data = cargo[1]
            email_data['sender'] = sender
            return ('rcpt', (stream, email_data))
    else:
        stream.wfile.write(bad_request+cr_lf)
        return ('done', cargo)        

Here, if the request is not recognized or invalid, the client sees the bad_request message, and the connection is closed, since control passes to the done end-state.

I followed Tyma’s example and defined bad_request as “550 No such user” (which, as he notes, is ironic, since Mailinator accepts email sent to any user).

It also doesn’t conform to the protocol, since I’m supposed to give different error messages at different nodes, but since clients are always disconnected after any type of invalid request, it hardly matters what they see in that scenario.

If a client is well-behaved, the final method called is process() which decides what to do with the client’s email. The data dict will contain three parameters: ‘sender’ (the email address of the sender), ‘recipients’ (a list of email addresses), and ‘data’ (the contents which followed the DATA command ahead of the final ‘.’).

def process (cargo):
    email_data = cargo[1]
    # do something with the email_data dict here
    return ('done', cargo)

Basically, this is where the data can be saved to disk/db (so that it can be served by a web browser later, e.g.), MIME-parsed (to remove attachments, etc.), or just trashed (if you have reason to believe the sender is a spambot or zombie network, e.g.).

Tyma describes various measures for dealing with attacks from spambots and zombies which I haven’t implemented here, but would be relatively easy to add to both the data() and process() functions.

Obtaining the ip address of the client is done using the stream.client_address[0] attribute.