1 # Copyright (C) 2011 by Jan Moskyto Matejka <moskyto@atrey.karlin.mff.cuni.cz>
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 from Mailman import mm_cfg
14 from Mailman import Errors
15 from Mailman.Logging.Syslog import syslog
16 from Mailman.Handlers import Hold
17 from subprocess import Popen, PIPE
20 """Do custom filtering.
22 Messages are passed to a custom script for filtering.
25 # This is the default location of the filter script
26 GLOBAL_FILTER_COMMAND = getattr(mm_cfg, 'GLOBAL_FILTER_COMMAND', '/var/lib/mailman/scripts/filter')
28 class FilterDiscard(Errors.DiscardMessage):
29 '''The filter wants to discard the message'''
30 def __init__(self, rea, rej):
31 Errors.DiscardMessage.__init__(self)
35 class FilterHold(Errors.HoldMessage):
36 '''The filter wants to hold the message'''
37 def __init__(self, rea, rej):
38 Errors.HoldMessage.__init__(self)
42 def process(mlist, msg, msgdata):
43 sender = msg.get_sender(use_envelope=0)
44 def not_a_delimiter(str):
49 if (str.replace("=",'') == '\n'):
54 filter = Popen(args=GLOBAL_FILTER_COMMAND, stdin=PIPE, stdout=PIPE)
55 filter.stdin.write(str(msg))
58 syslog('error', 'We got SIGPIPE from the filter on %s post from %s: %s' % (mlist.real_name, msg.get_sender(), e))
59 Hold.hold_for_approval(mlist, msg, msgdata, FilterHold("Filter dead.", "Your mail is held for moderation because of internal rules."))
62 r = filter.stdout.readline()
63 while (not_a_delimiter(r)):
65 r = filter.stdout.readline()
68 r = filter.stdout.readline()
69 while (not_a_delimiter(r)):
71 r = filter.stdout.readline()
73 reason = reason.strip()
74 rejection = rejection.strip()
81 Hold.hold_for_approval(mlist, msg, msgdata, FilterHold(reason, rejection))
83 syslog('vette', '%s post from %s discarded: %s' % (mlist.real_name, msg.get_sender(), reason))
84 raise FilterDiscard(reason, rejection)
86 syslog('error', 'The filter returned on %s post from %s some strange state: %s' % (mlist.real_name, msg.get_sender(), state))
87 Hold.hold_for_approval(mlist, msg, msgdata, FilterHold("The post is held for UNDEFINED reason.", "The post is held for UNDEFINED reason."))