Move parse_header to Milter.utils.

Test case for delayed DSN parsing.
Fix plock when source missing or cannot set owner/group.
This commit is contained in:
Stuart Gathman
2007-01-19 23:31:38 +00:00
parent 393aa6140a
commit 4c72135b0e
8 changed files with 112 additions and 66 deletions
+39 -54
View File
@@ -1,6 +1,12 @@
#!/usr/bin/env python
# A simple milter that has grown quite a bit.
# $Log$
# Revision 1.87 2007/01/18 16:48:44 customdesigned
# Doc update.
# Parse From header for delayed failure detection.
# Don't check reputation of trusted host.
# Track IP reputation only when missing PTR.
#
# Revision 1.86 2007/01/16 05:17:29 customdesigned
# REJECT after data for blacklisted emails - so in case of mistakes, a
# legitimate sender will know what happened.
@@ -76,11 +82,10 @@ import gc
import anydbm
import Milter.dsn as dsn
from Milter.dynip import is_dynip as dynip
from Milter.utils import iniplist,parse_addr,ip4re
from Milter.utils import iniplist,parse_addr,parse_header,ip4re
from Milter.config import MilterConfigParser
from fnmatch import fnmatchcase
from email.Header import decode_header
from email.Utils import getaddresses,parseaddr
# Import gossip if available
@@ -328,30 +333,26 @@ def read_config(list):
srs_domain.add(cp.getdefault('srs','fwdomain'))
banned_users = cp.getlist('srs','banned_users')
def parse_header(val):
"""Decode headers gratuitously encoded to hide the content.
"""
try:
h = decode_header(val)
if not len(h) or (not h[0][1] and len(h) == 1): return val
u = []
for s,enc in h:
if enc:
try:
u.append(unicode(s,enc))
except LookupError:
u.append(unicode(s))
else:
u.append(unicode(s))
u = ''.join(u)
for enc in ('us-ascii','iso-8859-1','utf8'):
def findsrs(fp):
lastln = None
for ln in fp:
if lastln:
if ln[0].isspace() and ln[0] != '\n':
lastln += ln
continue
try:
return u.encode(enc)
except UnicodeError: continue
except UnicodeDecodeError: pass
except LookupError: pass
except email.Errors.HeaderParseError: pass
return val
name,val = lastln.rstrip().split(None,1)
pos = val.find('<SRS')
if pos >= 0:
return srs.reverse(val[pos+1:-1])
except: continue
lnl = ln.lower()
if lnl.startswith('action:'):
if lnl.split()[-1] != 'failed': break
for k in ('message-id:','x-mailer:','sender:'):
if lnl.startswith(k):
lastln = ln
break
class SPFPolicy(object):
"Get SPF policy by result from sendmail style access file."
@@ -1362,35 +1363,19 @@ class bmsMilter(Milter.Milter):
# check for delayed bounce
if self.delayed_failure:
self.fp.seek(0)
lastln = None
for ln in self.fp:
if lastln:
if ln[0].isspace() and ln[0] != '\n':
lastln += ln
continue
try:
name,val = lastln.rstrip().split(None,1)
pos = val.find('<SRS')
if pos >= 0:
sender = srs.reverse(val[pos+1:-1])
cbv_cache[sender] = 500,self.delayed_failure,time.time()
try:
# save message for debugging
fname = tempfile.mktemp(".dsn")
os.rename(self.tempname,fname)
except:
fname = self.tempname
self.tempname = None
self.log('BLACKLIST:',sender,fname)
return Milter.DISCARD
except: continue
lnl = ln.lower()
if lnl.startswith('action:'):
if lnl.split()[-1] != 'failed': break
for k in ('message-id:','x-mailer:','sender:'):
if lnl.startswith(k):
lastln = ln
break
sender = findsrs(self.fp)
if sender:
cbv_cache[sender] = 500,self.delayed_failure,time.time()
try:
# save message for debugging
fname = tempfile.mktemp(".dsn")
os.rename(self.tempname,fname)
except:
fname = self.tempname
self.tempname = None
self.log('BLACKLIST:',sender,fname)
return Milter.DISCARD
# analyze external mail for spam
spam_checked = self.check_spam() # tag or quarantine for spam