Support temperror policy in access.

This commit is contained in:
Stuart Gathman
2007-11-01 20:09:14 +00:00
parent 5386e08ca5
commit 69369c3b2a
2 changed files with 67 additions and 6 deletions
+34 -6
View File
@@ -1,6 +1,10 @@
#!/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.115 2007/10/10 18:23:54 customdesigned
# Send quarantine DSN to SPF pass (official or guessed) only.
# Reject blacklisted email too big for dspam.
#
# Revision 1.114 2007/10/10 18:07:50 customdesigned # Revision 1.114 2007/10/10 18:07:50 customdesigned
# Check porn keywords in From header field. # Check porn keywords in From header field.
# #
@@ -256,6 +260,7 @@ hello_blacklist = ()
smart_alias = {} smart_alias = {}
dspam_dict = None dspam_dict = None
dspam_users = {} dspam_users = {}
dspam_train = {}
dspam_userdir = None dspam_userdir = None
dspam_exempt = {} dspam_exempt = {}
dspam_whitelist = {} dspam_whitelist = {}
@@ -387,6 +392,7 @@ def read_config(list):
dspam_users = cp.getaddrdict('dspam','dspam_users') dspam_users = cp.getaddrdict('dspam','dspam_users')
dspam_userdir = cp.getdefault('dspam','dspam_userdir') dspam_userdir = cp.getdefault('dspam','dspam_userdir')
dspam_screener = cp.getlist('dspam','dspam_screener') dspam_screener = cp.getlist('dspam','dspam_screener')
dspam_train = set(cp.getlist('dspam','dspam_train'))
dspam_reject = cp.getlist('dspam','dspam_reject') dspam_reject = cp.getlist('dspam','dspam_reject')
dspam_internal = cp.getboolean('dspam','dspam_internal') dspam_internal = cp.getboolean('dspam','dspam_internal')
if cp.has_option('dspam','dspam_sizelimit'): if cp.has_option('dspam','dspam_sizelimit'):
@@ -539,6 +545,12 @@ class SPFPolicy(object):
policy = 'REJECT' policy = 'REJECT'
return policy return policy
def getTempErrorPolicy(self):
policy = self.getPolicy('spf-temperror:')
if not policy:
policy = 'REJECT'
return policy
def getPassPolicy(self): def getPassPolicy(self):
policy = self.getPolicy('spf-pass:') policy = self.getPolicy('spf-pass:')
if not policy: if not policy:
@@ -895,8 +907,21 @@ class bmsMilter(Milter.Milter):
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'):
policy = p.getTempErrorPolicy()
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.setreply(str(code),'4.3.0',txt,
'We cannot accept your email until the DNS server for %s' % q.o,
'is operational for TXT record queries.'
)
return Milter.TEMPFAIL
res,code,txt = 'none',250,'EXT: ignoring DNS error'
hres = None hres = None
if res not in ('pass','error','temperror'): if res != 'pass':
if self.mailfrom != '<>': if self.mailfrom != '<>':
# check hello name via spf unless spf pass # check hello name via spf unless spf pass
h = spf.query(self.connectip,'',self.hello_name,receiver=receiver) h = spf.query(self.connectip,'',self.hello_name,receiver=receiver)
@@ -1012,10 +1037,6 @@ class bmsMilter(Milter.Milter):
'We cannot accept mail from %s until this is corrected.' % q.o 'We cannot accept mail from %s until this is corrected.' % q.o
) )
return Milter.REJECT return Milter.REJECT
if res in ('error','temperror'):
self.log('TEMPFAIL: SPF %s %i %s' % (res,code,txt))
self.setreply(str(code),'4.3.0',txt)
return Milter.TEMPFAIL
kv = {} kv = {}
if hres and q.h != q.o: if hres and q.h != q.o:
kv['helo_spf'] = hres kv['helo_spf'] = hres
@@ -1473,8 +1494,13 @@ class bmsMilter(Milter.Milter):
elif self.blacklist: elif self.blacklist:
txt = ds.check_spam(user,txt,self.recipients, txt = ds.check_spam(user,txt,self.recipients,
force_result=dspam.DSR_ISSPAM) force_result=dspam.DSR_ISSPAM)
else: elif user in dspam_train:
txt = ds.check_spam(user,txt,self.recipients) txt = ds.check_spam(user,txt,self.recipients)
else:
txt = ds.check_spam(user,txt,self.recipients,classify=True)
if txt:
self.add_header("X-DSpam-Score",'%f' % ds.probability)
return False
if not txt: if not txt:
# DISCARD if quarrantined for any recipient. It # DISCARD if quarrantined for any recipient. It
# will be resent to all recipients if they submit # will be resent to all recipients if they submit
@@ -1697,6 +1723,8 @@ class bmsMilter(Milter.Milter):
template_name = 'permerror' template_name = 'permerror'
elif res == 'neutral': elif res == 'neutral':
template_name = 'neutral' template_name = 'neutral'
elif res in ('error','temperror'):
template_name = 'temperror'
else: else:
template_name = 'strike3' template_name = 'strike3'
rc = self.send_dsn(q,msg,template_name) rc = self.send_dsn(q,msg,template_name)
+33
View File
@@ -0,0 +1,33 @@
To: %(sender)s
From: postmaster@%(receiver)s
Subject: Critical DNS configuration error
Auto-Submitted: auto-generated (configuration error)
This is an automatically generated Delivery Status Notification.
THIS IS A WARNING MESSAGE ONLY.
YOU DO *NOT* NEED TO RESEND YOUR MESSAGE.
Delivery to the following recipients has been delayed.
%(rcpt)s
Subject: %(subject)s
Received-SPF: %(spf_result)s
Your DNS server is not responding to TXT queries. In other words,
it is BROKEN. You need to get somebody to fix it ASAP. We
are attempting to do TXT queries to see if you have an SPF record.
See http://openspf.org
We are sending you this message to alert you to the fact that
you have problems with your DNS.
If you need further assistance, please do not hesitate to
contact me again.
Kind regards,
postmaster@%(receiver)s