MTA Integrations

Here is the recommended placement of the authentication check in a typical mail flow:

 

Note: checkID has an option "Quick pre-screen for heavily-spamming IPs", which can be used to

reject mail that isn't worth even one Registry query.  Currently, it uses the Spamhaus IP blacklist

for these rejects.  The IP Blacklist block uses other, more aggressive blacklists.

 

We still need help with these MTAs:

Sendmail

Postfix

 Exchange

Exim

Qmail

 

 

We have a Python function checkID() that does all the authentication work.  We need an interface to each MTA that will allow the Python script to be edited, without having to change or re-compile the MTA.

 

 

Sendmail already has a Python milter interface, which we could adapt.  http://sourceforge.net/projects/pymilter   The others might be done with a C-wrapper that can be compiled into any MTA written in C.  I'm thinking of something like Example 20-6 in Programming Python, 2nd ed.

 

The functions we need in the MTA are:

1) Support for a new ID command, following the rules for SMTP extensions.

2) Calling checkID with the connection IP address and the strings from the HELO, ID, and MAIL FROM commands.

3) Implementation of the actions ACCEPT, REJECT, etc.

4) Sending the SMTP_reply returned by checkID to the SMTP client (sender).

5) Prepending the headers returned by checkID to any forwarded message.

 

Here is the interface in Python:

 

def checkID( IP=None, ID=None, H=None, S=None, R=[], Hdrs=[], Body=None ):

    '''

Check that ID authorizes sending email from a machine with address IP.

 

H, S, and R are the rest of the envelope information, whatever is known at the

time of this call.

ID should be left None if there is no declared ID.

H and S are the names from the HELO/EHLO and MAIL FROM commands.

R is a list of addresses from the RCPT TO command.

 

Returns ( action, SMTP_reply, headers )

 

  action: 'ACCEPT', 'REJECT', 'FILTER', 'CONTINUE', 'TEMPFAIL', 'DISCARD'

    see http://www.milter.org/milter_api/api.html

 

  SMTP_reply = ( SMTP_code, Xcode, explanation )

    SMTP_code: SMTP Reply Code per RFC-2821

    Xcode:  Enhanced Mail System Status Code per RFC-3463

 

  headers = [header0, header1, ...]

    header0 = {'label': 'Authent:',

               'text': <standard authentication parameters> }

    headerN = {'label': <method-specific label:>,

               'text':  <method-specific text>   }

   

    Headers to be pre-pended in the order listed.  'header0' is the very first

    header from this Administrative Domain, 'header1' is above that, etc.  Other

    headers may be inserted in this list if required by a method, e.g. SPF

    requires that the 'Received:' header for the border MTA be below its header.

 

    Text strings have no line breaks. Folding white space

    should be added before prepending a long header.

 

>>> checkID('192.0.2.1', 'example.net')

('REJECT', (550, '5.7.1', "Sending MTA '192.0.2.1' not authorized by \

'example.net'"), [])

 

>>> checkID('192.0.2.1', 'example.com')

('ACCEPT', (250, '', 'Sender OK'), \

[{'text': '192.0.2.1 example.com SPF1 PASS ratings=S1:A,M2:A,H1:B', \

'label': 'Authent:'}])

  

    '''

9/29/05