Persist blacklisting from delayed DSNs.

This commit is contained in:
Stuart Gathman
2007-01-25 22:47:26 +00:00
parent 83529320ae
commit 21e3c6f489
6 changed files with 34 additions and 13 deletions
+9 -6
View File
@@ -10,6 +10,11 @@
# CBV results. # CBV results.
# #
# $Log$ # $Log$
# Revision 1.6 2007/01/19 23:31:38 customdesigned
# Move parse_header to Milter.utils.
# Test case for delayed DSN parsing.
# Fix plock when source missing or cannot set owner/group.
#
# Revision 1.5 2007/01/11 19:59:40 customdesigned # Revision 1.5 2007/01/11 19:59:40 customdesigned
# Purge old entries in auto_whitelist and send_dsn logs. # Purge old entries in auto_whitelist and send_dsn logs.
# #
@@ -129,12 +134,10 @@ class AddrCache(object):
def __setitem__(self,sender,res): def __setitem__(self,sender,res):
lsender = sender.lower() lsender = sender.lower()
now = time.time() now = time.time()
cached = self.has_key(sender) self.cache[lsender] = (now,res)
if not cached: if not res and self.fname:
self.cache[lsender] = (now,res) s = time.strftime(AddrCache.time_format,time.localtime(now))
if not res and self.fname: print >>open(self.fname,'a'),sender,s # log refreshed senders
s = time.strftime(AddrCache.time_format,time.localtime(now))
print >>open(self.fname,'a'),sender,s # log refreshed senders
def __len__(self): def __len__(self):
return len(self.cache) return len(self.cache)
+1
View File
@@ -2,6 +2,7 @@ Here is a history of user visible changes to Python milter.
0.8.8 move AddrCache, parse_addr, iniplist, parse_header to Milter package 0.8.8 move AddrCache, parse_addr, iniplist, parse_header to Milter package
fix plock for missing source and can't change owner/group fix plock for missing source and can't change owner/group
add sample spfmilter.py milter add sample spfmilter.py milter
private_relay config option
0.8.7 Move spf module to pyspf 0.8.7 Move spf module to pyspf
Prevent PTR cache poisoning Prevent PTR cache poisoning
More lame bounce heuristics More lame bounce heuristics
+10 -5
View File
@@ -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.90 2007/01/23 19:46:20 customdesigned
# Add private relay.
#
# Revision 1.89 2007/01/22 02:46:01 customdesigned # Revision 1.89 2007/01/22 02:46:01 customdesigned
# Convert tabs to spaces. # Convert tabs to spaces.
# #
@@ -359,7 +362,7 @@ def findsrs(fp):
lnl = ln.lower() lnl = ln.lower()
if lnl.startswith('action:'): if lnl.startswith('action:'):
if lnl.split()[-1] != 'failed': break if lnl.split()[-1] != 'failed': break
for k in ('message-id:','x-mailer:','sender:'): for k in ('message-id:','x-mailer:','sender:','references:'):
if lnl.startswith(k): if lnl.startswith(k):
lastln = ln lastln = ln
break break
@@ -907,6 +910,7 @@ class bmsMilter(Milter.Milter):
self.log('REJECT: RELAY:',to) self.log('REJECT: RELAY:',to)
self.setreply('550','5.7.1','Unauthorized relay for %s' % domain) self.setreply('550','5.7.1','Unauthorized relay for %s' % domain)
return Milter.REJECT return Milter.REJECT
# non DSN mail to SRS address will bounce due to invalid local part # non DSN mail to SRS address will bounce due to invalid local part
canon_to = '@'.join(t) canon_to = '@'.join(t)
self.recipients.append(canon_to) self.recipients.append(canon_to)
@@ -941,8 +945,8 @@ class bmsMilter(Milter.Milter):
self.reject_spam = False self.reject_spam = False
self.smart_alias(to) self.smart_alias(to)
# get recipient after virtusertable aliasing # get recipient after virtusertable aliasing
#rcpt = self.getsymval("{rcpt_addr}") rcpt = self.getsymval("{rcpt_addr}")
#self.log("rcpt-addr",rcpt); self.log("rcpt-addr",rcpt);
return Milter.CONTINUE return Milter.CONTINUE
# Heuristic checks for spam headers # Heuristic checks for spam headers
@@ -1379,7 +1383,9 @@ class bmsMilter(Milter.Milter):
self.fp.seek(0) self.fp.seek(0)
sender = findsrs(self.fp) sender = findsrs(self.fp)
if sender: if sender:
cbv_cache[sender] = 500,self.delayed_failure,time.time() cbv_cache[sender] = 550,self.delayed_failure
# make blacklisting persistent, since delayed DSNs are expensive
blacklist[sender] = None
try: try:
# save message for debugging # save message for debugging
fname = tempfile.mktemp(".dsn") fname = tempfile.mktemp(".dsn")
@@ -1596,7 +1602,6 @@ class bmsMilter(Milter.Milter):
self.log('TEMPFAIL:',desc) self.log('TEMPFAIL:',desc)
self.setreply('450','4.2.0',*desc.splitlines()) self.setreply('450','4.2.0',*desc.splitlines())
return Milter.TEMPFAIL return Milter.TEMPFAIL
if len(res) < 3: res += time.time(),
cbv_cache[sender] = res cbv_cache[sender] = res
self.log('REJECT:',desc) self.log('REJECT:',desc)
self.setreply('550','5.7.1',*desc.splitlines()) self.setreply('550','5.7.1',*desc.splitlines())
+1
View File
@@ -9,6 +9,7 @@
<li><a href="logmsgs.html">Log&nbsp;Messages</a> <li><a href="logmsgs.html">Log&nbsp;Messages</a>
<li><a href="http://bmsi.com/mailman/listinfo/pymilter">Mailing&nbsp;List</a> <li><a href="http://bmsi.com/mailman/listinfo/pymilter">Mailing&nbsp;List</a>
<li><a href="credits.html">CREDITS</a> <li><a href="credits.html">CREDITS</a>
<li><a href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=139894&amp;type=1" width="88" height="31" border="0" alt="SourceForge.net Logo" /></a>
<h3>Links</h3> <h3>Links</h3>
<li><a href="http://www.milter.org/milter_api/api.html">C&nbsp;API</a> <li><a href="http://www.milter.org/milter_api/api.html">C&nbsp;API</a>
<li><a href="http://www.milter.org/">Milter.Org</a> <li><a href="http://www.milter.org/">Milter.Org</a>
+1
View File
@@ -181,6 +181,7 @@ rm -rf $RPM_BUILD_ROOT
- move parse_header to Milter.utils - move parse_header to Milter.utils
- fix plock for missing source and can't change owner/group - fix plock for missing source and can't change owner/group
- add sample spfmilter.py milter - add sample spfmilter.py milter
- private_relay config option
* Sat Nov 04 2006 Stuart Gathman <stuart@bmsi.com> 0.8.7-1 * Sat Nov 04 2006 Stuart Gathman <stuart@bmsi.com> 0.8.7-1
- More lame bounce heuristics - More lame bounce heuristics
- SPF moved to pyspf RPM - SPF moved to pyspf RPM
+12 -2
View File
@@ -8,13 +8,12 @@ class AddrCacheTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self.fname = 'test.dat' self.fname = 'test.dat'
self.cache = AddrCache(fname=self.fname)
def tearDown(self): def tearDown(self):
os.remove(self.fname) os.remove(self.fname)
def testAdd(self): def testAdd(self):
cache = self.cache cache = AddrCache(fname=self.fname)
cache['foo@bar.com'] = None cache['foo@bar.com'] = None
cache.addperm('baz@bar.com') cache.addperm('baz@bar.com')
cache['temp@bar.com'] = 'testing' cache['temp@bar.com'] = 'testing'
@@ -26,6 +25,17 @@ class AddrCacheTestCase(unittest.TestCase):
self.failUnless(len(s) == 2) self.failUnless(len(s) == 2)
self.failUnless(s[0].startswith('foo@bar.com ')) self.failUnless(s[0].startswith('foo@bar.com '))
self.assertEquals(s[1].strip(),'baz@bar.com') self.assertEquals(s[1].strip(),'baz@bar.com')
# check that new result overrides old
cache['temp@bar.com'] = None
self.failUnless(not cache['temp@bar.com'])
def testDomain(self):
fp = open(self.fname,'w')
print >>fp,'spammer.com'
fp.close()
cache = AddrCache(fname=self.fname)
cache.load(self.fname,30)
self.failUnless('spammer.com' in cache)
def suite(): def suite():
s = unittest.makeSuite(AddrCacheTestCase,'test') s = unittest.makeSuite(AddrCacheTestCase,'test')