
``smtpd`` --- SMTP Server
*************************

**Source code:** Lib/smtpd.py

======================================================================

This module offers several classes to implement SMTP (email) servers.

Several server implementations are present; one is a generic do-
nothing implementation, which can be overridden, while the other two
offer specific mail-sending strategies.

Additionally the SMTPChannel may be extended to implement very
specific interaction behaviour with SMTP clients.


SMTPServer Objects
==================

class class smtpd.SMTPServer(localaddr, remoteaddr)

   Create a new ``SMTPServer`` object, which binds to local address
   *localaddr*.  It will treat *remoteaddr* as an upstream SMTP
   relayer.  It inherits from ``asyncore.dispatcher``, and so will
   insert itself into ``asyncore``'s event loop on instantiation.

   process_message(peer, mailfrom, rcpttos, data)

      Raise ``NotImplementedError`` exception. Override this in
      subclasses to do something useful with this message. Whatever
      was passed in the constructor as *remoteaddr* will be available
      as the ``_remoteaddr`` attribute. *peer* is the remote host's
      address, *mailfrom* is the envelope originator, *rcpttos* are
      the envelope recipients and *data* is a string containing the
      contents of the e-mail (which should be in **RFC 2822** format).

   channel_class

      Override this in subclasses to use a custom ``SMTPChannel`` for
      managing SMTP clients.


DebuggingServer Objects
=======================

class class smtpd.DebuggingServer(localaddr, remoteaddr)

   Create a new debugging server.  Arguments are as per
   ``SMTPServer``. Messages will be discarded, and printed on stdout.


PureProxy Objects
=================

class class smtpd.PureProxy(localaddr, remoteaddr)

   Create a new pure proxy server. Arguments are as per
   ``SMTPServer``. Everything will be relayed to *remoteaddr*.  Note
   that running this has a good chance to make you into an open relay,
   so please be careful.


MailmanProxy Objects
====================

class class smtpd.MailmanProxy(localaddr, remoteaddr)

   Create a new pure proxy server. Arguments are as per
   ``SMTPServer``. Everything will be relayed to *remoteaddr*, unless
   local mailman configurations knows about an address, in which case
   it will be handled via mailman.  Note that running this has a good
   chance to make you into an open relay, so please be careful.


SMTPChannel Objects
===================

class class smtpd.SMTPChannel(server, conn, addr)

   Create a new ``SMTPChannel`` object which manages the communication
   between the server and a single SMTP client.

   To use a custom SMTPChannel implementation you need to override the
   ``SMTPServer.channel_class`` of your ``SMTPServer``.

   The ``SMTPChannel`` has the following instance variables:

   smtp_server

      Holds the ``SMTPServer`` that spawned this channel.

   conn

      Holds the socket object connecting to the client.

   addr

      Holds the address of the client, the second value returned by
      socket.accept()

   received_lines

      Holds a list of the line strings (decoded using UTF-8) received
      from the client. The lines have their "rn" line ending
      translated to "n".

   smtp_state

      Holds the current state of the channel. This will be either
      ``COMMAND`` initially and then ``DATA`` after the client sends a
      "DATA" line.

   seen_greeting

      Holds a string containing the greeting sent by the client in its
      "HELO".

   mailfrom

      Holds a string containing the address identified in the "MAIL
      FROM:" line from the client.

   rcpttos

      Holds a list of strings containing the addresses identified in
      the "RCPT TO:" lines from the client.

   received_data

      Holds a string containing all of the data sent by the client
      during the DATA state, up to but not including the terminating
      "rn.rn".

   fqdn

      Holds the fully-qualified domain name of the server as returned
      by ``socket.getfqdn()``.

   peer

      Holds the name of the client peer as returned by
      ``conn.getpeername()`` where ``conn`` is ``conn``.

   The ``SMTPChannel`` operates by invoking methods named
   ``smtp_<command>`` upon reception of a command line from the
   client. Built into the base ``SMTPChannel`` class are methods for
   handling the following commands (and responding to them
   appropriately):

   +----------+---------------------------------------------------------------------+
   | Command  | Action taken                                                        |
   +==========+=====================================================================+
   | HELO     | Accepts the greeting from the client and stores it in               |
   |          | ``seen_greeting``.                                                  |
   +----------+---------------------------------------------------------------------+
   | NOOP     | Takes no action.                                                    |
   +----------+---------------------------------------------------------------------+
   | QUIT     | Closes the connection cleanly.                                      |
   +----------+---------------------------------------------------------------------+
   | MAIL     | Accepts the "MAIL FROM:" syntax and stores the supplied address as  |
   |          | ``mailfrom``.                                                       |
   +----------+---------------------------------------------------------------------+
   | RCPT     | Accepts the "RCPT TO:" syntax and stores the supplied addresses in  |
   |          | the ``rcpttos`` list.                                               |
   +----------+---------------------------------------------------------------------+
   | RSET     | Resets the ``mailfrom``, ``rcpttos``, and ``received_data``, but    |
   |          | not the greeting.                                                   |
   +----------+---------------------------------------------------------------------+
   | DATA     | Sets the internal state to ``DATA`` and stores remaining lines from |
   |          | the client in ``received_data`` until the terminator "rn.rn" is     |
   |          | received.                                                           |
   +----------+---------------------------------------------------------------------+
