aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman/Queue
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/Queue')
-rw-r--r--Mailman/Queue/BounceRunner.py15
-rw-r--r--Mailman/Queue/CommandRunner.py31
-rw-r--r--Mailman/Queue/IncomingRunner.py24
-rw-r--r--Mailman/Queue/NewsRunner.py22
-rwxr-xr-x[-rw-r--r--]Mailman/Queue/OutgoingRunner.py3
-rw-r--r--Mailman/Queue/Switchboard.py6
6 files changed, 68 insertions, 33 deletions
diff --git a/Mailman/Queue/BounceRunner.py b/Mailman/Queue/BounceRunner.py
index d219d6e9..651039d6 100644
--- a/Mailman/Queue/BounceRunner.py
+++ b/Mailman/Queue/BounceRunner.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2008 by the Free Software Foundation, Inc.
+# Copyright (C) 2001-2015 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
@@ -30,6 +30,7 @@ from Mailman import mm_cfg
from Mailman import Utils
from Mailman import LockFile
from Mailman.Message import UserNotification
+from Mailman.Bouncer import _BounceInfo
from Mailman.Bouncers import BouncerAPI
from Mailman.Queue.Runner import Runner
from Mailman.Queue.sbcache import get_switchboard
@@ -151,6 +152,14 @@ class BounceMixin:
try:
op, addr, bmsg = mlist.pend_confirm(token)
info = mlist.getBounceInfo(addr)
+ if not info:
+ # info was deleted before probe bounce was received.
+ # Just create a new info.
+ info = _BounceInfo(addr,
+ 0.0,
+ time.localtime()[:3],
+ mlist.bounce_you_are_disabled_warnings
+ )
mlist.disableBouncingMember(addr, info, bmsg)
# Only save the list if we're unlocking it
if not locked:
@@ -244,6 +253,7 @@ class BounceRunner(Runner, BounceMixin):
return
# If that still didn't return us any useful addresses, then send it on
# or discard it.
+ addrs = filter(None, addrs)
if not addrs:
syslog('bounce',
'%s: bounce message w/no discernable addresses: %s',
@@ -254,7 +264,8 @@ class BounceRunner(Runner, BounceMixin):
# BAW: It's possible that there are None's in the list of addresses,
# although I'm unsure how that could happen. Possibly ScanMessages()
# can let None's sneak through. In any event, this will kill them.
- addrs = filter(None, addrs)
+ # addrs = filter(None, addrs)
+ # MAS above filter moved up so we don't try to queue an empty list.
self._queue_bounces(mlist.internal_name(), addrs, msg)
_doperiodic = BounceMixin._doperiodic
diff --git a/Mailman/Queue/CommandRunner.py b/Mailman/Queue/CommandRunner.py
index b63b050c..c5cc3d94 100644
--- a/Mailman/Queue/CommandRunner.py
+++ b/Mailman/Queue/CommandRunner.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2015 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
@@ -12,7 +12,8 @@
#
# 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.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
"""-request robot command queue runner."""
@@ -132,22 +133,34 @@ class Results:
__import__(modname)
handler = sys.modules[modname]
# ValueError can be raised if cmd has dots in it.
- except (ImportError, ValueError):
+ # and KeyError if cmd is otherwise good but ends with a dot.
+ except (ImportError, ValueError, KeyError):
# If we're on line zero, it was the Subject: header that didn't
# contain a command. It's possible there's a Re: prefix (or
# localized version thereof) on the Subject: line that's messing
# things up. Pop the prefix off and try again... once.
#
+ # At least one MUA (163.com web mail) has been observed that
+ # inserts 'Re:' with no following space, so try to account for
+ # that too.
+ #
# If that still didn't work it isn't enough to stop processing.
# BAW: should we include a message that the Subject: was ignored?
- if not self.subjcmdretried and args:
+ #
+ # But first, be sure we're looking at the Subject: and not past
+ # it already.
+ if self.lineno != 0:
+ return BADCMD
+ if self.subjcmdretried < 1:
+ self.subjcmdretried += 1
+ if re.search('^.*:.+', cmd):
+ cmd = re.sub('.*:', '', cmd).lower()
+ return self.do_command(cmd, args)
+ if self.subjcmdretried < 2 and args:
self.subjcmdretried += 1
- cmd = args.pop(0)
+ cmd = args.pop(0).lower()
return self.do_command(cmd, args)
- if self.lineno <> 0:
- return BADCMD
- else:
- return BADSUBJ
+ return BADSUBJ
if handler.process(self, args):
return STOP
else:
diff --git a/Mailman/Queue/IncomingRunner.py b/Mailman/Queue/IncomingRunner.py
index 71d93919..2c6c2815 100644
--- a/Mailman/Queue/IncomingRunner.py
+++ b/Mailman/Queue/IncomingRunner.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2015 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
@@ -157,14 +157,32 @@ class IncomingRunner(Runner):
os._exit(1)
except Errors.DiscardMessage:
# Throw the message away; we need do nothing else with it.
- syslog('vette', 'Message discarded, msgid: %s',
- msg.get('message-id', 'n/a'))
+ # We do need to push the current handler back in the pipeline
+ # just in case the syslog call throws an exception and the
+ # message is shunted.
+ pipeline.insert(0, handler)
+ syslog('vette', """Message discarded, msgid: %s'
+ list: %s,
+ handler: %s""",
+ msg.get('message-id', 'n/a'),
+ mlist.real_name, handler)
return 0
except Errors.HoldMessage:
# Let the approval process take it from here. The message no
# longer needs to be queued.
return 0
except Errors.RejectMessage, e:
+ # Log this.
+ # We do need to push the current handler back in the pipeline
+ # just in case the syslog call or BounceMessage throws an
+ # exception and the message is shunted.
+ pipeline.insert(0, handler)
+ syslog('vette', """Message rejected, msgid: %s
+ list: %s,
+ handler: %s,
+ reason: %s""",
+ msg.get('message-id', 'n/a'),
+ mlist.real_name, handler, e.notice())
mlist.BounceMessage(msg, msgdata, e)
return 0
except:
diff --git a/Mailman/Queue/NewsRunner.py b/Mailman/Queue/NewsRunner.py
index 44850063..449532fb 100644
--- a/Mailman/Queue/NewsRunner.py
+++ b/Mailman/Queue/NewsRunner.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2000-2005 by the Free Software Foundation, Inc.
+# Copyright (C) 2000-2015 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
@@ -111,20 +111,12 @@ def prepare_message(mlist, msg, msgdata):
del msg['subject']
msg['subject'] = stripped_subject
# Add the appropriate Newsgroups: header
- ngheader = msg['newsgroups']
- if ngheader is not None:
- # See if the Newsgroups: header already contains our linked_newsgroup.
- # If so, don't add it again. If not, append our linked_newsgroup to
- # the end of the header list
- ngroups = [s.strip() for s in ngheader.split(',')]
- if mlist.linked_newsgroup not in ngroups:
- ngroups.append(mlist.linked_newsgroup)
- # Subtitute our new header for the old one.
- del msg['newsgroups']
- msg['Newsgroups'] = COMMASPACE.join(ngroups)
- else:
- # Newsgroups: isn't in the message
- msg['Newsgroups'] = mlist.linked_newsgroup
+ if msg['newsgroups'] is not None:
+ # This message is gated from our list to it's associated usnet group.
+ # If it has a Newsgroups: header mentioning other groups, it's not
+ # up to us to post it to those groups.
+ del msg['newsgroups']
+ msg['Newsgroups'] = mlist.linked_newsgroup
# Note: We need to be sure two messages aren't ever sent to the same list
# in the same process, since message ids need to be unique. Further, if
# messages are crossposted to two Usenet-gated mailing lists, they each
diff --git a/Mailman/Queue/OutgoingRunner.py b/Mailman/Queue/OutgoingRunner.py
index 0f51b663..defaf02d 100644..100755
--- a/Mailman/Queue/OutgoingRunner.py
+++ b/Mailman/Queue/OutgoingRunner.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2000-2007 by the Free Software Foundation, Inc.
+# Copyright (C) 2000-2012 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
@@ -89,6 +89,7 @@ class OutgoingRunner(Runner, BounceMixin):
syslog('error', 'Cannot connect to SMTP server %s on port %s',
mm_cfg.SMTPHOST, port)
self.__logged = True
+ self._snooze(0)
return True
except Errors.SomeRecipientsFailed, e:
# Handle local rejects of probe messages differently.
diff --git a/Mailman/Queue/Switchboard.py b/Mailman/Queue/Switchboard.py
index bd1cd357..a2c31263 100644
--- a/Mailman/Queue/Switchboard.py
+++ b/Mailman/Queue/Switchboard.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2008 by the Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 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
@@ -184,8 +184,8 @@ class Switchboard:
else:
os.unlink(bakfile)
except EnvironmentError, e:
- syslog('error', 'Failed to unlink/preserve backup file: %s',
- bakfile)
+ syslog('error', 'Failed to unlink/preserve backup file: %s\n%s',
+ bakfile, e)
def files(self, extension='.pck'):
times = {}