CBV policy sends no DSN. DSN policy sends DSN.
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# A simple milter that has grown quite a bit.
|
# A simple milter that has grown quite a bit.
|
||||||
# $Log$
|
# $Log$
|
||||||
|
# Revision 1.124 2008/08/05 18:04:06 customdesigned
|
||||||
|
# Send quarantine DSN to SPF PASS only.
|
||||||
|
#
|
||||||
# Revision 1.123 2008/07/29 21:59:29 customdesigned
|
# Revision 1.123 2008/07/29 21:59:29 customdesigned
|
||||||
# Parse ESMTP params
|
# Parse ESMTP params
|
||||||
#
|
#
|
||||||
@@ -942,17 +945,13 @@ class bmsMilter(Milter.Milter):
|
|||||||
res,code,txt = q.check()
|
res,code,txt = q.check()
|
||||||
q.result = res
|
q.result = res
|
||||||
if res in ('unknown','permerror') and q.perm_error and q.perm_error.ext:
|
if res in ('unknown','permerror') and q.perm_error and q.perm_error.ext:
|
||||||
self.cbv_needed = (q,res) # report SPF syntax error to sender
|
self.cbv_needed = (q,'permerror') # report SPF syntax error to sender
|
||||||
res,code,txt = q.perm_error.ext # extended (lax processing) result
|
res,code,txt = q.perm_error.ext # extended (lax processing) result
|
||||||
txt = 'EXT: ' + txt
|
txt = 'EXT: ' + txt
|
||||||
p = SPFPolicy(q.s)
|
p = SPFPolicy(q.s)
|
||||||
# FIXME: try:finally to close policy db, or reuse with lock
|
# FIXME: try:finally to close policy db, or reuse with lock
|
||||||
if res in ('error','temperror'):
|
if res in ('error','temperror'):
|
||||||
policy = p.getTempErrorPolicy()
|
if self.need_cbv(p.getTempErrorPolicy(),q,'temperror'):
|
||||||
if policy == 'CBV':
|
|
||||||
if self.mailfrom != '<>':
|
|
||||||
self.cbv_needed = (q,res)
|
|
||||||
elif policy != 'OK':
|
|
||||||
self.log('TEMPFAIL: SPF %s %i %s' % (res,code,txt))
|
self.log('TEMPFAIL: SPF %s %i %s' % (res,code,txt))
|
||||||
self.setreply(str(code),'4.3.0',txt,
|
self.setreply(str(code),'4.3.0',txt,
|
||||||
'We cannot accept your email until the DNS server for %s' % q.o,
|
'We cannot accept your email until the DNS server for %s' % q.o,
|
||||||
@@ -1006,11 +1005,9 @@ class bmsMilter(Milter.Milter):
|
|||||||
and hres != 'pass':
|
and hres != 'pass':
|
||||||
# this bad boy has no credentials whatsoever
|
# this bad boy has no credentials whatsoever
|
||||||
policy = p.getNonePolicy()
|
policy = p.getNonePolicy()
|
||||||
if policy == 'CBV':
|
if policy in ('CBV','DNS'):
|
||||||
if self.mailfrom != '<>':
|
|
||||||
self.cbv_needed = (q,ores) # accept, but inform sender via DSN
|
|
||||||
self.offenses = 3 # ban ip if any bad recipient
|
self.offenses = 3 # ban ip if any bad recipient
|
||||||
elif policy != 'OK':
|
if self.need_cbv(policy,q,'strike3'):
|
||||||
self.log('REJECT: no PTR, HELO or SPF')
|
self.log('REJECT: no PTR, HELO or SPF')
|
||||||
self.setreply('550','5.7.1',
|
self.setreply('550','5.7.1',
|
||||||
"You must have a valid HELO or publish SPF: http://www.openspf.org ",
|
"You must have a valid HELO or publish SPF: http://www.openspf.org ",
|
||||||
@@ -1021,11 +1018,7 @@ class bmsMilter(Milter.Milter):
|
|||||||
)
|
)
|
||||||
return self.offense() # ban ip if too many bad MFROMs
|
return self.offense() # ban ip if too many bad MFROMs
|
||||||
if res in ('deny', 'fail'):
|
if res in ('deny', 'fail'):
|
||||||
policy = p.getFailPolicy()
|
if self.need_cbv(p.getFailPolicy(),q,'fail'):
|
||||||
if policy == 'CBV':
|
|
||||||
if self.mailfrom != '<>':
|
|
||||||
self.cbv_needed = (q,res)
|
|
||||||
elif policy != 'OK':
|
|
||||||
self.log('REJECT: SPF %s %i %s' % (res,code,txt))
|
self.log('REJECT: SPF %s %i %s' % (res,code,txt))
|
||||||
self.setreply(str(code),'5.7.1',txt)
|
self.setreply(str(code),'5.7.1',txt)
|
||||||
# A proper SPF fail error message would read:
|
# A proper SPF fail error message would read:
|
||||||
@@ -1033,11 +1026,7 @@ class bmsMilter(Milter.Milter):
|
|||||||
# "forged.org" in the sender address. Contact <postmaster@forged.org>.
|
# "forged.org" in the sender address. Contact <postmaster@forged.org>.
|
||||||
return Milter.REJECT
|
return Milter.REJECT
|
||||||
if res == 'softfail':
|
if res == 'softfail':
|
||||||
policy = p.getSoftfailPolicy()
|
if self.need_cbv(p.getSoftfailPolicy(),q,'softfail'):
|
||||||
if policy == 'CBV':
|
|
||||||
if self.mailfrom != '<>':
|
|
||||||
self.cbv_needed = (q,res)
|
|
||||||
elif policy != 'OK':
|
|
||||||
self.log('REJECT: SPF %s %i %s' % (res,code,txt))
|
self.log('REJECT: SPF %s %i %s' % (res,code,txt))
|
||||||
self.setreply('550','5.7.1',
|
self.setreply('550','5.7.1',
|
||||||
'SPF softfail: If you get this Delivery Status Notice, your email',
|
'SPF softfail: If you get this Delivery Status Notice, your email',
|
||||||
@@ -1048,12 +1037,7 @@ class bmsMilter(Milter.Milter):
|
|||||||
)
|
)
|
||||||
return Milter.REJECT
|
return Milter.REJECT
|
||||||
if res == 'neutral':
|
if res == 'neutral':
|
||||||
policy = p.getNeutralPolicy()
|
if self.need_cbv(p.getNeutralPolicy(),q,'neutral'):
|
||||||
if policy == 'CBV':
|
|
||||||
if self.mailfrom != '<>':
|
|
||||||
self.cbv_needed = (q,res)
|
|
||||||
# FIXME: this makes Received-SPF show wrong result
|
|
||||||
elif policy != 'OK':
|
|
||||||
self.log('REJECT: SPF neutral for',q.s)
|
self.log('REJECT: SPF neutral for',q.s)
|
||||||
self.setreply('550','5.7.1',
|
self.setreply('550','5.7.1',
|
||||||
'mail from %s must pass SPF: http://openspf.org/why.html' % q.o,
|
'mail from %s must pass SPF: http://openspf.org/why.html' % q.o,
|
||||||
@@ -1065,11 +1049,7 @@ class bmsMilter(Milter.Milter):
|
|||||||
)
|
)
|
||||||
return Milter.REJECT
|
return Milter.REJECT
|
||||||
if res in ('unknown','permerror'):
|
if res in ('unknown','permerror'):
|
||||||
policy = p.getPermErrorPolicy()
|
if self.need_cbv(p.getPermErrorPolicy(),q,'permerror'):
|
||||||
if policy == 'CBV':
|
|
||||||
if self.mailfrom != '<>':
|
|
||||||
self.cbv_needed = (q,res)
|
|
||||||
elif policy != 'OK':
|
|
||||||
self.log('REJECT: SPF %s %i %s' % (res,code,txt))
|
self.log('REJECT: SPF %s %i %s' % (res,code,txt))
|
||||||
# latest SPF draft recommends 5.5.2 instead of 5.7.1
|
# latest SPF draft recommends 5.5.2 instead of 5.7.1
|
||||||
self.setreply(str(code),'5.5.2',txt,
|
self.setreply(str(code),'5.5.2',txt,
|
||||||
@@ -1648,24 +1628,21 @@ class bmsMilter(Milter.Milter):
|
|||||||
self.log("TRAINSPAM:",screener,'X-Dspam-Score: %f' % ds.probability)
|
self.log("TRAINSPAM:",screener,'X-Dspam-Score: %f' % ds.probability)
|
||||||
|
|
||||||
def do_needed_cbv(self,msg):
|
def do_needed_cbv(self,msg):
|
||||||
q,res = self.cbv_needed
|
q,template_name = self.cbv_needed
|
||||||
if res == 'softfail':
|
|
||||||
template_name = 'softfail'
|
|
||||||
elif res in ('fail','deny'):
|
|
||||||
template_name = 'fail'
|
|
||||||
elif res in ('unknown','permerror'):
|
|
||||||
template_name = 'permerror'
|
|
||||||
elif res == 'neutral':
|
|
||||||
#template_name = 'neutral'
|
|
||||||
template_name = None
|
|
||||||
elif res in ('error','temperror'):
|
|
||||||
template_name = 'temperror'
|
|
||||||
else:
|
|
||||||
template_name = 'strike3'
|
|
||||||
rc = self.send_dsn(q,msg,template_name)
|
rc = self.send_dsn(q,msg,template_name)
|
||||||
self.cbv_needed = None
|
self.cbv_needed = None
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
def need_cbv(self,policy,q,tname):
|
||||||
|
if policy == 'CBV':
|
||||||
|
if self.mailfrom != '<>' and not self.cbv_needed:
|
||||||
|
self.cbv_needed = (q,None)
|
||||||
|
elif policy == 'DSN':
|
||||||
|
if self.mailfrom != '<>' and not self.cbv_needed:
|
||||||
|
self.cbv_needed = (q,tname)
|
||||||
|
elif policy != 'OK': return True
|
||||||
|
return False
|
||||||
|
|
||||||
def eom(self):
|
def eom(self):
|
||||||
if not self.fp:
|
if not self.fp:
|
||||||
return Milter.ACCEPT # no message collected - so no eom processing
|
return Milter.ACCEPT # no message collected - so no eom processing
|
||||||
|
|||||||
Reference in New Issue
Block a user