diff --git a/bms.py b/bms.py
index 6c704f2673a5fcb04536ed9ac820af05e6fa28b5..e967b85566371d5bb3984d426117c7c56609427b 100644
--- a/bms.py
+++ b/bms.py
@@ -1,6 +1,9 @@
 #!/usr/bin/env python
 # A simple milter that has grown quite a bit.
 # $Log$
+# Revision 1.74  2006/12/19 00:59:30  customdesigned
+# Add archive option to wiretap.
+#
 # Revision 1.73  2006/12/04 18:47:03  customdesigned
 # Reject multiple recipients to DSN.
 # Auto-disable gossip on DB error.
@@ -818,20 +821,27 @@ class bmsMilter(Milter.Milter):
     	or domain in blacklist:
       self.blacklist = True
       self.log("BLACKLIST",self.canon_from)
-    global gossip
-    if gossip and domain and rc == Milter.CONTINUE \
-    	and not self.internal_connection:
-      if self.spf and self.spf.result == 'pass':
-        qual = 'SPF'
-      else:
-        qual = self.connectip
-      try:
-	self.umis = gossip.umis(domain+qual,self.id+time.time())
-	res,hdr,val = gossip_node.query(self.umis,domain,qual,1)
-	self.add_header(hdr,val)
-      except:
-        gossip = None
-	raise
+    else:
+      global gossip
+      if gossip and domain and rc == Milter.CONTINUE \
+	  and not self.internal_connection:
+	if self.spf and self.spf.result == 'pass':
+	  qual = 'SPF'
+	elif res == 'pass':
+	  qual = 'GUESS'
+	else:
+	  qual = self.connectip
+	try:
+	  umis = gossip.umis(domain+qual,self.id+time.time())
+	  res,hdr,val = gossip_node.query(umis,domain,qual,1)
+	  self.add_header(hdr,val)
+	  a = val.split(',')
+	  self.reputation = int(a[-2])
+	  self.confidence = int(a[-1])
+	  self.umis = umis
+	except:
+	  gossip = None
+	  raise
     return rc
 
   def check_spf(self):
@@ -884,6 +894,8 @@ class bmsMilter(Milter.Milter):
 	  res,code,txt = q.best_guess('v=spf1 a/24 mx/24')
 	else:
 	  res,code,txt = q.best_guess()
+	if res != 'pass' and hres == 'pass' and spf.domainmatch([q.h],q.o):
+	  res = 'pass'	# get a guessed pass for valid matching HELO 
       if self.missing_ptr and ores == 'none' and res != 'pass' \
       		and hres != 'pass':
 	# this bad boy has no credentials whatsoever
@@ -998,6 +1010,7 @@ class bmsMilter(Milter.Milter):
 	    # Currently, a sendmail map reverses SRS.  We just log it here.
 	    self.log("srs rcpt:",newaddr)
 	  self.dspam = False	# verified as reply to mail we sent
+	  self.blacklist = False
 	except:
 	  if not (self.internal_connection or self.trusted_relay):
 	    if srsre.match(oldaddr):
@@ -1022,7 +1035,8 @@ class bmsMilter(Milter.Milter):
       if self.discard:
         self.del_recipient(to)
       # don't check userlist if signed MFROM for now
-      if users and not newaddr and not user.lower() in users:
+      userl = user.lower()
+      if users and not newaddr and not userl in users:
         self.log('REJECT: RCPT TO:',to)
 	return Milter.REJECT
       # FIXME: should dspam_exempt be case insensitive?
@@ -1030,7 +1044,17 @@ class bmsMilter(Milter.Milter):
         self.forward = False
       exempt_users = dspam_exempt.get(domain,())
       if user in exempt_users or '' in exempt_users:
+	if self.blacklist:
+	  self.log('REJECT: BLACKLISTED')
+	  self.setreply('550','5.7.1','Sending domain has been blacklisted')
+	  return Milter.REJECT
 	self.dspam = False
+      if userl != 'postmaster' and self.umis	\
+      	and self.reputation < -50 and self.confidence > 1:
+        self.log('REJECT: REPUTATION')
+	self.setreply('550','5.7.1','Your domain has been sending mostly spam')
+	return Milter.REJECT
+
       if domain in hide_path:
         self.hidepath = True
       if not domain in dspam_reject:
@@ -1196,7 +1220,7 @@ class bmsMilter(Milter.Milter):
 	    hd = t[1].lower()
 	    if hd == mf_domain or mf_domain.endswith('.'+hd): break
 	else:
-	  for f in msg.get_all('from'):
+	  for f in msg.get_all('from',[]):
 	    self.log(f)
 	  sender = msg.get_all('sender')
 	  if sender:
diff --git a/milter.spec b/milter.spec
index a41f9b7601be6e52f8607a47c167d33b82f2d331..6bb15cfd14c91dbaf8bb12e562b227ee795e6bca 100644
--- a/milter.spec
+++ b/milter.spec
@@ -175,9 +175,9 @@ rm -rf $RPM_BUILD_ROOT
 
 %changelog
 * Sat Nov 04 2006 Stuart Gathman <stuart@bmsi.com> 0.8.7-1
-- Prevent PTR cache poisoning
 - More lame bounce heuristics
 - SPF moved to pyspf RPM
+- wiretap archive option
 * Tue May 23 2006 Stuart Gathman <stuart@bmsi.com> 0.8.6-2
 - Support CBV timeout
 - Support fail template, headers in templates