Import note_error from pyspf. Handle timeout on type99 lookup

specially (sender actually has no SPF record and a braindead DNS server).
This commit is contained in:
Stuart Gathman
2006-03-21 18:48:51 +00:00
parent 6102d641c5
commit ec4f9fdd99
2 changed files with 42 additions and 24 deletions
+7
View File
@@ -1,3 +1,10 @@
For selected domains, check users via CBV before accepting mail. Cache
results.
Allow blacklisted emails as well as domains in blacklist.log. Use same
data structure as autowhitelist.log. Add emails blacklisted via CBV
so that they are remembered across milter restarts.
Make all dictionaries work like honeypot. Do not train as ham unless Make all dictionaries work like honeypot. Do not train as ham unless
whitelisted. Train on blacklisted messages, or spam feedback. whitelisted. Train on blacklisted messages, or spam feedback.
+35 -24
View File
@@ -47,6 +47,11 @@ For news, bugfixes, etc. visit the home page for this implementation at
# Terrence is not responding to email. # Terrence is not responding to email.
# #
# $Log$ # $Log$
# Revision 1.19 2006/02/24 02:12:54 customdesigned
# Properly report hard PermError (lax mode fails also) by always setting
# perm_error attribute with PermError exception. Improve reporting of
# invalid domain PermError.
#
# Revision 1.18 2005/12/29 19:15:35 customdesigned # Revision 1.18 2005/12/29 19:15:35 customdesigned
# Handle NULL MX # Handle NULL MX
# #
@@ -539,6 +544,17 @@ class query(object):
finally: finally:
self.d = tmp self.d = tmp
def note_error(self,*msg):
if self.strict:
raise PermError(*msg)
# if lax mode, note error and continue
if not self.perm_error:
try:
raise PermError(*msg)
except PermError, x:
self.perm_error = x
return self.perm_error
def validate_mechanism(self,mech): def validate_mechanism(self,mech):
"""Parse and validate a mechanism. """Parse and validate a mechanism.
Returns mech,m,arg,cidrlength,result Returns mech,m,arg,cidrlength,result
@@ -570,13 +586,8 @@ class query(object):
# default pass # default pass
result = 'pass' result = 'pass'
if m in COMMON_MISTAKES: if m in COMMON_MISTAKES:
try: self.note_error('Unknown mechanism found',mech)
raise PermError('Unknown mechanism found',mech) m = COMMON_MISTAKES[m]
except PermError, x:
if self.strict: raise
m = COMMON_MISTAKES[m]
if not self.perm_error:
self.perm_error = x
if m in ('a', 'mx', 'ptr', 'exists', 'include'): if m in ('a', 'mx', 'ptr', 'exists', 'include'):
arg = self.expand(arg) arg = self.expand(arg)
@@ -591,15 +602,12 @@ class query(object):
return mech,m,arg,cidrlength,result return mech,m,arg,cidrlength,result
if m in ALL_MECHANISMS: if m in ALL_MECHANISMS:
return mech,m,arg,cidrlength,result return mech,m,arg,cidrlength,result
try: if m[1:] in ALL_MECHANISMS:
if m[1:] in ALL_MECHANISMS: x = self.note_error(
raise PermError( 'Unknown qualifier, IETF draft para 4.6.1, found in', mech)
'Unknown qualifier, IETF draft para 4.6.1, found in', else:
mech) x = self.note_error('Unknown mechanism found',mech)
raise PermError('Unknown mechanism found',mech) return mech,m,arg,cidrlength,x
except PermError, x:
if self.strict: raise
return mech,m,arg,cidrlength,x
def check0(self, spf,recursion): def check0(self, spf,recursion):
"""Test this query information against SPF text. """Test this query information against SPF text.
@@ -728,14 +736,10 @@ class query(object):
def check_lookups(self): def check_lookups(self):
self.lookups = self.lookups + 1 self.lookups = self.lookups + 1
if self.lookups > MAX_LOOKUP*4:
raise PermError('More than %d DNS lookups'%MAX_LOOKUP*4)
if self.lookups > MAX_LOOKUP: if self.lookups > MAX_LOOKUP:
try: self.note_error('Too many DNS lookups')
if self.strict or not self.perm_error:
raise PermError('Too many DNS lookups')
except PermError,x:
if self.strict or self.lookups > MAX_LOOKUP*4:
raise x
self.perm_error = x
def get_explanation(self, spec): def get_explanation(self, spec):
"""Expand an explanation.""" """Expand an explanation."""
@@ -875,7 +879,14 @@ class query(object):
def dns_99(self, domainname): def dns_99(self, domainname):
"Get a list of type SPF=99 records for a domain name." "Get a list of type SPF=99 records for a domain name."
if domainname: if domainname:
return [''.join(a) for a in self.dns(domainname, 'SPF')] try:
return [''.join(a) for a in self.dns(domainname, 'SPF')]
except TempError,x:
if self.strict: raise x
self.note_error(
'DNS responds, but times out on type99 (SPF) query: %s'%
domainname
)
return [] return []
def dns_mx(self, domainname): def dns_mx(self, domainname):