[Pymilter] Possible to use a milter for reverse SRS?

Stuart D. Gathman stuart at gathman.org
Fri Jan 25 10:49:33 EST 2019


On Fri, 25 Jan 2019, Melanie Dymond Harper wrote:

> I'm in the process of testing an SRS setup -- we need to be able to
> forward email for some customers from domains managed here to their own
> email accounts. We have srsmilter working the way it ought to for
> outbound mail, so far so good; is it possible to configure it to handle
> returned (bounced) mail to SRS-encoded addresses as well? The

Oh my.  That was a very misleading thing for me to do.  srsmilter.py is 
a proof of concept for using the (at the time) new chgfrom milter API.
Notice that it can't handle multiple recicients well due to the 
nature of the environment chgfrom is called from.

The SRS I use in production uses pysrs.py (a socket map) in conjunction
with the pysrs.m4 feature for sendmail.cf for outgoing mail.

Incoming SRS is handled off stage, in my case by the milter package.
It is really rather mean of me.  srsmilter, even if chgfrom doesn't
handle multiple recipients well, should at least provide a basic
implementation of incoming SRS!

So, the thing to do is extract the basics from bms.py in the milter
package, and add them to srsmilter.py.  Invoking chgfrom should be 
configurable, as it is limited, so that pysrs.py can be used instead
for outgoing SRS with sendmail.  And srsmilter would then provide
simple processing of SRS bounces for either case.

Note that pysrs.m4 also handles reverse by simply unwrapping SRS
bounces.  Invalid SRS bounces are then rejected as 'unknown user'.

Handling SRS bounces in a milter simply lets you do more accurate
errors, e.g. bms.py responds to an invalid SRS bounce like this:

             if not (self.internal_connection or self.trusted_relay):
               if srsre.match(oldaddr):
                 self.log("REJECT: srs spoofed:",oldaddr)
                 self.setreply('550','5.7.1','Invalid SRS signature')
                 return Milter.REJECT

Which is more informative than "unknown user".

So, outgoing SRS can be handled via CF and a socket map in pysrs.py,
or via chgfrom milter API in srsmilter.py.

Incoming SRS can be handle via CF and a socket map in pysrs.py with
an "invalid user" response. Or, in the future - I think I can get 
something to test by Jan 29 - by srsmilter.py issuing an SRS specific
rejection.  It is only a few lines - they just need to be the right
lines.

In bms.py, I made srs_reject_spoofed a config boolean, thinking that 
I might want to give deliberately ambiguous errors to spammers.  But 
it has turned out that spammers don't really do anything with that kind
of response, and being helpful to mail admins is more important.

-- 
 	      Stuart D. Gathman <stuart at gathman.org>
"Confutatis maledictis, flamis acribus addictis" - background song for
a Microsoft sponsored "Where do you want to go from here?" commercial.


More information about the Pymilter mailing list