summaryrefslogtreecommitdiff
path: root/Mailman/Handlers/SpamDetect.py
diff options
context:
space:
mode:
authorBarry Warsaw2008-02-01 22:21:05 -0500
committerBarry Warsaw2008-02-01 22:21:05 -0500
commitb6f3ba4c9ebe821dd2c4676d7397fe5312b72a36 (patch)
tree5803f890642e5272b856e30869abd630b43271bc /Mailman/Handlers/SpamDetect.py
parentc1cc921b691eb60445cf28bc66a59b02b3cd09a4 (diff)
downloadmailman-b6f3ba4c9ebe821dd2c4676d7397fe5312b72a36.tar.gz
mailman-b6f3ba4c9ebe821dd2c4676d7397fe5312b72a36.tar.zst
mailman-b6f3ba4c9ebe821dd2c4676d7397fe5312b72a36.zip
SpamDetect is gone, so the chains/rules implementation experiment is deemed a
success and will now be merged into the trunk. Move the Truth rule into the built-in rules package in a separate module, and add a test. Modify IChainLink so that the rule and chain attributes are not names but indeed the actual ILink or IChain object directly. Update the chains.process() function accordingly. Remove the IChain.get_rule() method. Don't derive BuiltInChain from Chain and don't make it an IMutableChain. It's now just an IChain, and is implemented concretely. Refactor the HeaderMatchChain and friends so that it can be used with both the global HEADER_MATCHES variable and the list-specific header_matches variable, which has exactly the same semantics. Oh yeah, get rid of the list's header_filter_rules attribute and replace it with header_matches so that the semantics match, it's easy to explain, and it's all nice and clean.
Diffstat (limited to 'Mailman/Handlers/SpamDetect.py')
-rw-r--r--Mailman/Handlers/SpamDetect.py130
1 files changed, 0 insertions, 130 deletions
diff --git a/Mailman/Handlers/SpamDetect.py b/Mailman/Handlers/SpamDetect.py
deleted file mode 100644
index f45b52a32..000000000
--- a/Mailman/Handlers/SpamDetect.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Copyright (C) 1998-2007 by the Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-# USA.
-
-"""Do more detailed spam detection.
-
-This module hard codes site wide spam detection. By hacking the
-KNOWN_SPAMMERS variable, you can set up more regular expression matches
-against message headers. If spam is detected the message is discarded
-immediately.
-
-TBD: This needs to be made more configurable and robust.
-"""
-
-import re
-
-from cStringIO import StringIO
-from email.Generator import Generator
-
-from Mailman import Errors
-from Mailman import i18n
-from Mailman.Handlers.Hold import hold_for_approval
-from Mailman.configuration import config
-
-# First, play footsie with _ so that the following are marked as translated,
-# but aren't actually translated until we need the text later on.
-def _(s):
- return s
-
-
-
-class SpamDetected(Errors.DiscardMessage):
- """The message contains known spam"""
-
-class HeaderMatchHold(Errors.HoldMessage):
- reason = _('The message headers matched a filter rule')
-
-
-# And reset the translator
-_ = i18n._
-
-
-
-class Tee:
- def __init__(self, outfp_a, outfp_b):
- self._outfp_a = outfp_a
- self._outfp_b = outfp_b
-
- def write(self, s):
- self._outfp_a.write(s)
- self._outfp_b.write(s)
-
-
-# Class to capture the headers separate from the message body
-class HeaderGenerator(Generator):
- def __init__(self, outfp, mangle_from_=True, maxheaderlen=78):
- Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
- self._headertxt = ''
-
- def _write_headers(self, msg):
- sfp = StringIO()
- oldfp = self._fp
- self._fp = Tee(oldfp, sfp)
- try:
- Generator._write_headers(self, msg)
- finally:
- self._fp = oldfp
- self._headertxt = sfp.getvalue()
-
- def header_text(self):
- return self._headertxt
-
-
-
-def process(mlist, msg, msgdata):
- if msgdata.get('approved'):
- return
- # Now do header_filter_rules
- # TK: Collect headers in sub-parts because attachment filename
- # extension may be a clue to possible virus/spam.
- headers = ''
- for p in msg.walk():
- g = HeaderGenerator(StringIO())
- g.flatten(p)
- headers += g.header_text()
- # Now reshape headers (remove extra CR and connect multiline).
- headers = re.sub('\n+', '\n', headers)
- headers = re.sub('\n\s', ' ', headers)
- for patterns, action, empty in mlist.header_filter_rules:
- if action == config.DEFER:
- continue
- for pattern in patterns.splitlines():
- if pattern.startswith('#'):
- continue
- # ignore 'empty' patterns
- if not pattern.strip():
- continue
- if re.search(pattern, headers, re.IGNORECASE|re.MULTILINE):
- if action == config.DISCARD:
- raise Errors.DiscardMessage
- if action == config.REJECT:
- if msgdata.get('toowner'):
- # Don't send rejection notice if addressed to '-owner'
- # because it may trigger a loop of notices if the
- # sender address is forged. We just discard it here.
- raise Errors.DiscardMessage
- raise Errors.RejectMessage(
- _('Message rejected by filter rule match'))
- if action == config.HOLD:
- if msgdata.get('toowner'):
- # Don't hold '-owner' addressed message. We just
- # pass it here but list-owner can set this to be
- # discarded on the GUI if he wants.
- return
- hold_for_approval(mlist, msg, msgdata, HeaderMatchHold)
- if action == config.ACCEPT:
- return