diff options
author | Mark Sapiro <msapiro@value.net> | 2011-02-07 11:59:23 -0800 |
---|---|---|
committer | Mark Sapiro <msapiro@value.net> | 2011-02-07 11:59:23 -0800 |
commit | ea9bee8858f3a9940412164e0908bc7d12614063 (patch) | |
tree | 07dca439b93a936c541426583e2de6c1edb12290 /Mailman | |
parent | 0def772b0be9114e58226665941009a9a5566256 (diff) | |
download | mailman2-ea9bee8858f3a9940412164e0908bc7d12614063.tar.gz mailman2-ea9bee8858f3a9940412164e0908bc7d12614063.tar.xz mailman2-ea9bee8858f3a9940412164e0908bc7d12614063.zip |
- A new mm_cfg.py setting RESPONSE_INCLUDE_LEVEL has been added to control
how much of the original message is included in automatic responses to
email commands. The default is 2 to preserve the prior behavior of
including the full message. Setting this to 1 in mm_cfg.py will include
only the original headers, and 0 will include none of the original. It
is recommended to set this to 0 in mm_cfg.py to minimize the effects of
backscatter. Bug #265835.
- A new mm_cfg.py setting DEFAULT_RESPOND_TO_POST_REQUESTS has been added
to control the default for respond_to_post_requests for new lists. It is
set to Yes for backwards compatibility, but it is recommended that
serious consideration be given to setting it to No. Bug #266051.
- A new mm_cfg.py setting DISCARD_MESSAGE_WITH_NO_COMMAND has been added to
control whether a message to the -request address without any commands or
a message to -confirm whose To: address doesn't match VERP_CONFIRM_REGEXP
is responded to or just logged. It defaults to Yes which is different
from prior behavior. Bug #410236.
Diffstat (limited to 'Mailman')
-rw-r--r-- | Mailman/Defaults.py.in | 34 | ||||
-rw-r--r-- | Mailman/MailList.py | 4 | ||||
-rw-r--r-- | Mailman/Queue/CommandRunner.py | 58 |
3 files changed, 77 insertions, 19 deletions
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index e1ede271..1bf8362d 100644 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -1,6 +1,6 @@ # -*- python -*- -# Copyright (C) 1998-2010 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2011 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 @@ -690,7 +690,7 @@ VERP_CONFIRM_FORMAT = '%(addr)s+%(cookie)s' # To: "local_part@host" <local_part@host> # and may even fold the header when replying, so we skip everything up to '<' # if any and include ($s) so dot will match the newline in a folded header. -VERP_CONFIRM_REGEXP = r'(?s)^(.*<)?(?P<addr>.+)\+(?P<cookie>[^@+]+)@.*$' +VERP_CONFIRM_REGEXP = r'(?s)^(.*<)?(?P<addr>.+)\+(?P<cookie>[0-9a-f]{40})@.*$' # Set this to Yes to enable VERP-like (more user friendly) confirmations VERP_CONFIRMATIONS = No @@ -707,6 +707,36 @@ MAX_AUTORESPONSES_PER_DAY = 10 ##### +# Backscatter mitigation +##### + +# This controls whether a message to the -request address without any +# commands or a message to -confirm whose To: address doesn't match +# VERP_CONFIRM_REGEXP above is responded to or just logged. +DISCARD_MESSAGE_WITH_NO_COMMAND = Yes + +# This controls how much of the original message is included in automatic +# responses to email commands. The values are: +# 0 - Do not include any unprocessed or ignored commands. Do not include +# the original message. +# 1 - Do not include any unprocessed or ignored commands. Include only the +# headers from the original message. +# 2 - Include unprocessed and ignored commands. Include the complete original +# message. +# +# In order to minimize the effect of backscatter due to spam sent to +# administrative addresses, it is recommended to set this to 0, however the +# default is 2 for backwards compatibility. +RESPONSE_INCLUDE_LEVEL = 2 + +# This sets the default for respond_to_post_requests for new lists. It is +# set to Yes for backwards compatibility, but it is recommended that serious +# consideration be given to setting it to No. +DEFAULT_RESPOND_TO_POST_REQUESTS = Yes + + + +##### # Qrunner defaults ##### diff --git a/Mailman/MailList.py b/Mailman/MailList.py index a7efd986..504effa7 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2010 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2011 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 @@ -314,7 +314,7 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin, self.new_member_options = mm_cfg.DEFAULT_NEW_MEMBER_OPTIONS # This stuff is configurable - self.respond_to_post_requests = 1 + self.respond_to_post_requests = mm_cfg.DEFAULT_RESPOND_TO_POST_REQUESTS self.advertised = mm_cfg.DEFAULT_LIST_ADVERTISED self.max_num_recipients = mm_cfg.DEFAULT_MAX_NUM_RECIPIENTS self.max_message_size = mm_cfg.DEFAULT_MAX_MESSAGE_SIZE diff --git a/Mailman/Queue/CommandRunner.py b/Mailman/Queue/CommandRunner.py index 3155f22f..b63b050c 100644 --- a/Mailman/Queue/CommandRunner.py +++ b/Mailman/Queue/CommandRunner.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2010 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2011 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 @@ -46,6 +46,10 @@ from email.MIMEText import MIMEText from email.MIMEMessage import MIMEMessage NL = '\n' +CONTINUE = 0 +STOP = 1 +BADCMD = 2 +BADSUBJ = 3 try: True, False @@ -105,15 +109,19 @@ class Results: def process(self): # Now, process each line until we find an error. The first # non-command line found stops processing. - stop = False + found = BADCMD + ret = CONTINUE for line in self.commands: if line and line.strip(): args = line.split() cmd = args.pop(0).lower() - stop = self.do_command(cmd, args) + ret = self.do_command(cmd, args) + if ret == STOP or ret == CONTINUE: + found = ret self.lineno += 1 - if stop: + if ret == STOP or ret == BADCMD: break + return found def do_command(self, cmd, args=None): if args is None: @@ -136,8 +144,14 @@ class Results: self.subjcmdretried += 1 cmd = args.pop(0) return self.do_command(cmd, args) - return self.lineno <> 0 - return handler.process(self, args) + if self.lineno <> 0: + return BADCMD + else: + return BADSUBJ + if handler.process(self, args): + return STOP + else: + return CONTINUE def send_response(self): # Helper @@ -156,7 +170,7 @@ Attached is your original message. # Ignore empty lines unprocessed = [line for line in self.commands[self.lineno:] if line and line.strip()] - if unprocessed: + if unprocessed and mm_cfg.RESPONSE_INCLUDE_LEVEL >= 2: resp.append(_('\n- Unprocessed:')) resp.extend(indent(unprocessed)) if not unprocessed and not self.results: @@ -165,7 +179,7 @@ Attached is your original message. No commands were found in this message. To obtain instructions, send a message containing just the word "help". """))) - if self.ignored: + if self.ignored and mm_cfg.RESPONSE_INCLUDE_LEVEL >= 2: resp.append(_('\n- Ignored:')) resp.extend(indent(self.ignored)) resp.append(_('\n- Done.\n\n')) @@ -196,7 +210,15 @@ To obtain instructions, send a message containing just the word "help". lang=self.msgdata['lang']) msg.set_type('multipart/mixed') msg.attach(results) - orig = MIMEMessage(self.msg) + if mm_cfg.RESPONSE_INCLUDE_LEVEL == 1: + self.msg.set_payload( + _('Message body suppressed by Mailman site configuration\n')) + if mm_cfg.RESPONSE_INCLUDE_LEVEL == 0: + orig = MIMEText(_( + 'Original message suppressed by Mailman site configuration\n' + ), _charset=charset) + else: + orig = MIMEMessage(self.msg) msg.attach(orig) msg.send(self.mlist) @@ -236,17 +258,23 @@ class CommandRunner(Runner): # mylist-join, or mylist-leave, and the message metadata will contain # a key to which one was used. try: + ret = BADCMD if msgdata.get('torequest'): - res.process() + ret = res.process() elif msgdata.get('tojoin'): - res.do_command('join') + ret = res.do_command('join') elif msgdata.get('toleave'): - res.do_command('leave') + ret = res.do_command('leave') elif msgdata.get('toconfirm'): mo = re.match(mm_cfg.VERP_CONFIRM_REGEXP, msg.get('to', '')) if mo: - res.do_command('confirm', (mo.group('cookie'),)) - res.send_response() - mlist.Save() + ret = res.do_command('confirm', (mo.group('cookie'),)) + if ret == BADCMD and mm_cfg.DISCARD_MESSAGE_WITH_NO_COMMAND: + syslog('vette', + 'No command, message discarded, msgid: %s', + msg.get('message-id', 'n/a')) + else: + res.send_response() + mlist.Save() finally: mlist.Unlock() |