Negative feedback for bad headers. Purge cache logs on startup.

This commit is contained in:
Stuart Gathman
2007-01-11 04:31:26 +00:00
parent a875ac7834
commit c0aa632e16
3 changed files with 81 additions and 4 deletions
+11 -2
View File
@@ -10,6 +10,9 @@
# CBV results.
#
# $Log$
# Revision 1.3 2007/01/08 23:20:54 customdesigned
# Get user feedback.
#
# Revision 1.2 2007/01/05 23:33:55 customdesigned
# Make blacklist an AddrCache
#
@@ -22,6 +25,7 @@
# This code is under the GNU General Public License. See COPYING for details.
import time
from plock import PLock
class AddrCache(object):
time_format = '%Y%b%d %H:%M:%S %Z'
@@ -39,6 +43,8 @@ class AddrCache(object):
cache = {}
self.cache = cache
now = time.time()
lock = PLock(self.fname)
wfp = lock.lock()
try:
too_old = now - age*24*60*60 # max age in days
for ln in open(self.fname):
@@ -46,11 +52,14 @@ class AddrCache(object):
rcpt,ts = ln.strip().split(None,1)
l = time.strptime(ts,AddrCache.time_format)
t = time.mktime(l)
if t > too_old:
if t < too_old: continue
cache[rcpt.lower()] = (t,None)
except:
cache[ln.strip().lower()] = (now,None)
except IOError: pass
wfp.write(ln)
lock.commit(self.fname+'.old')
except IOError:
lock.unlock()
def has_key(self,sender):
"True if sender is cached and has not expired."
+62
View File
@@ -0,0 +1,62 @@
# Author: Stuart D. Gathman <stuart@bmsi.com>
# Copyright 2001 Business Management Systems, Inc.
# This code is under the GNU General Public License. See COPYING for details.
import os
from time import sleep
class PLock(object):
"A simple /etc/passwd style lock,update,rename protocol for updating files."
def __init__(self,basename):
self.basename = basename
self.fp = None
def lock(self,lockname=None):
"Start an update transaction. Return FILE to write new version."
self.unlock()
if not lockname:
lockname = self.basename + '.lock'
self.lockname = lockname
st = os.stat(self.basename)
u = os.umask(0002)
try:
fd = os.open(lockname,os.O_WRONLY+os.O_CREAT+os.O_EXCL,st.st_mode|0660)
finally:
os.umask(u)
self.fp = os.fdopen(fd,'w')
try:
os.chown(self.lockname,-1,st.st_gid)
except:
self.unlock()
raise
return self.fp
def wlock(self,lockname=None):
"Wait until lock is free, then start an update transaction."
while True:
try:
return self.lock(lockname)
except OSError:
sleep(2)
def commit(self,backname=None):
"Commit update transaction with optional backup file."
if not self.fp:
raise IOError,"File not locked"
self.fp.close()
self.fp = None
if backname:
try:
os.remove(backname)
except OSError: pass
os.link(self.basename,backname)
os.rename(self.lockname,self.basename)
def unlock(self):
"Cancel update transaction."
if self.fp:
try:
self.fp.close()
except: pass
self.fp = None
os.remove(self.lockname)
+7 -1
View File
@@ -1,6 +1,9 @@
#!/usr/bin/env python
# A simple milter that has grown quite a bit.
# $Log$
# Revision 1.84 2007/01/10 04:44:25 customdesigned
# Documentation updates.
#
# Revision 1.83 2007/01/08 23:20:54 customdesigned
# Get user feedback.
#
@@ -1017,7 +1020,10 @@ class bmsMilter(Milter.Milter):
val = parse_header(hval)
if not self.internal_connection and not (self.blacklist or self.whitelist):
rc = self.check_header(name,val)
if rc != Milter.CONTINUE: return rc
if rc != Milter.CONTINUE:
if gossip and self.umis:
gossip_node.feedback(self.umis,1)
return rc
elif self.whitelist_sender and lname == 'subject':
# check for AutoReplys
vl = val.lower()