April 2024 - This site, and Kamaelia are being updated. There is significant work needed, and PRs are welcome.


Concrete Mail Core

This code enforces the basic statemachine that SMTP expects, switching between the various commands and finally results in forwarding on the SMTP command to the appropriate SMTP server. By itself, this can be used as a simple SMTP Proxy server.

This class is a subclass of MailHandler, and as such largely consists of methods overriding methods from MailHandler which are designed to be overridden.

Furthermore, it expects to forward any mail it accepts to another SMTP mail server, as transparently as possible. Thus this concrete mail core effectively forms the core of an SMTP proxy.


As it stands however, by default this mail proxy will not forward any mails to the internal server. In order to change this, you would need to subclass this server and replace the method "shouldWeAcceptMail" since that defaults to returning False

Example Usage

As noted, you are not expected to use this ConcreteMailHandler directly, but if you did, you would use it like this:

ServerCore(protocol=ConcreteMailHandler, port=1025)
At minimum, you would need to do this::
class SpamMeHandler(ConcreteMailHandler):
def shouldWeAcceptMail(self):
return True

ServerCore(protocol=SpamMeHandler, port=1025)

You could alternatively do this::
class SpamMeMailServer(ServerCore):
class protcol(ConcreteMailHandler):
def shouldWeAcceptMail(self):
return True


How does it work?

As noted this overrides all the methods relating to handling SMTP commands, and enforces the state machine that SMTP requires. It's particularly strict about this, in breach of Postel's law for two reasons -

  • It helps eradicate spam
  • because most spam systems are generally lax these days and most non-spam systems are generally strict

It was also primarily written in the context of a greylisting server.

Some core values it tracks with regard to a mail -
  • a list of recipients
  • the (claimed) sender
  • the (claimed) remote/client name
  • the actual client & local port/ip addresses

Once the client has finished sending the data for an email, the proxy forwards the mail to the local real SMTP server. Fundamentally this happens by making a connection to the real server using the TCPClient component, and then replaying all the lines the original server sent us to the local server.

(ie an inbox_log is built up with all data recieved from inbox "inbox" and then the contents of this are replayed when being sent to the local (real) SMTP mail server)


This class provides a large number of configuration options. You can either change this through subclassing or by providing as named arguments to the __init__ function. The options you have -

  • servername - The name this server will choose to use to identify itself
  • serverid - The string this server will use to identify itself (in terms of software in use)
  • smtp_ip - the ip address of the server you're proxying for/to
  • smtp_port - this is the port the server you're proxying for/to is listening on

The following attributes get set when a client connects -

  • peer - the IP address of the client
  • peerport - the port which the peer is connected from
  • local - the IP address the client has connected to
  • localport - the port which they're connected to


class ConcreteMailHandler(Kamaelia.Apps.Grey.MailHandler.MailHandler)


  • control : Shutdown & control messages regarding client side socket handling
  • tcp_inbox : This is where we get respones from the real SMTP server
  • tcp_control : This is where we get shutdown information from the real SMTP server
  • inbox : Data from the client connecting to the server comes in here


  • outbox : Data sent here goes back the the client connecting to the server
  • signal : Shutdown & control messages regarding client side socket handling
  • tcp_outbox : Data sent here is sent to the real SMTP server
  • tcp_signal : We send messages here to shutdown the connection to the real SMTP connection

Methods defined here


You should be using the inbox/outbox interface, not these methods (except construction). This documentation is designed as a roadmap as to their functionalilty for maintainers and new component developers.


__init__(self, **argv)




error(self, message)



handleData(self, command)


handleEhlo(self, command)

handleHelo(self, command)

handleHelp(self, command)

handleMail(self, command)

handleNoop(self, command)

handleQuit(self, command)

handleRcpt(self, command)

handleRset(self, command)

handleVrfy(self, command)


Methods inherited from Kamaelia.Apps.Grey.MailHandler.MailHandler :


Got a problem with the documentation? Something unclear that could be clearer? Want to help improve it? Constructive criticism is very welcome - especially if you can suggest a better rewording!

Please leave you feedback here in reply to the documentation thread in the Kamaelia blog.

-- Automatic documentation generator, 05 Jun 2009 at 03:01:38 UTC/GMT