Negative feedback for bad headers. Purge cache logs on startup.
This commit is contained in:
+12
-3
@@ -10,6 +10,9 @@
|
|||||||
# CBV results.
|
# CBV results.
|
||||||
#
|
#
|
||||||
# $Log$
|
# $Log$
|
||||||
|
# Revision 1.3 2007/01/08 23:20:54 customdesigned
|
||||||
|
# Get user feedback.
|
||||||
|
#
|
||||||
# Revision 1.2 2007/01/05 23:33:55 customdesigned
|
# Revision 1.2 2007/01/05 23:33:55 customdesigned
|
||||||
# Make blacklist an AddrCache
|
# Make blacklist an AddrCache
|
||||||
#
|
#
|
||||||
@@ -22,6 +25,7 @@
|
|||||||
# This code is under the GNU General Public License. See COPYING for details.
|
# This code is under the GNU General Public License. See COPYING for details.
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
from plock import PLock
|
||||||
|
|
||||||
class AddrCache(object):
|
class AddrCache(object):
|
||||||
time_format = '%Y%b%d %H:%M:%S %Z'
|
time_format = '%Y%b%d %H:%M:%S %Z'
|
||||||
@@ -39,6 +43,8 @@ class AddrCache(object):
|
|||||||
cache = {}
|
cache = {}
|
||||||
self.cache = cache
|
self.cache = cache
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
lock = PLock(self.fname)
|
||||||
|
wfp = lock.lock()
|
||||||
try:
|
try:
|
||||||
too_old = now - age*24*60*60 # max age in days
|
too_old = now - age*24*60*60 # max age in days
|
||||||
for ln in open(self.fname):
|
for ln in open(self.fname):
|
||||||
@@ -46,11 +52,14 @@ class AddrCache(object):
|
|||||||
rcpt,ts = ln.strip().split(None,1)
|
rcpt,ts = ln.strip().split(None,1)
|
||||||
l = time.strptime(ts,AddrCache.time_format)
|
l = time.strptime(ts,AddrCache.time_format)
|
||||||
t = time.mktime(l)
|
t = time.mktime(l)
|
||||||
if t > too_old:
|
if t < too_old: continue
|
||||||
cache[rcpt.lower()] = (t,None)
|
cache[rcpt.lower()] = (t,None)
|
||||||
except:
|
except:
|
||||||
cache[ln.strip().lower()] = (now,None)
|
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):
|
def has_key(self,sender):
|
||||||
"True if sender is cached and has not expired."
|
"True if sender is cached and has not expired."
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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.84 2007/01/10 04:44:25 customdesigned
|
||||||
|
# Documentation updates.
|
||||||
|
#
|
||||||
# Revision 1.83 2007/01/08 23:20:54 customdesigned
|
# Revision 1.83 2007/01/08 23:20:54 customdesigned
|
||||||
# Get user feedback.
|
# Get user feedback.
|
||||||
#
|
#
|
||||||
@@ -1017,7 +1020,10 @@ class bmsMilter(Milter.Milter):
|
|||||||
val = parse_header(hval)
|
val = parse_header(hval)
|
||||||
if not self.internal_connection and not (self.blacklist or self.whitelist):
|
if not self.internal_connection and not (self.blacklist or self.whitelist):
|
||||||
rc = self.check_header(name,val)
|
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':
|
elif self.whitelist_sender and lname == 'subject':
|
||||||
# check for AutoReplys
|
# check for AutoReplys
|
||||||
vl = val.lower()
|
vl = val.lower()
|
||||||
|
|||||||
Reference in New Issue
Block a user