aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman/Queue/IncomingRunner.py
diff options
context:
space:
mode:
author <>2003-01-02 05:25:50 +0000
committer <>2003-01-02 05:25:50 +0000
commitb132a73f15e432eaf43310fce9196ca0c0651465 (patch)
treec15f816ba7c4de99fef510e3bd75af0890d47441 /Mailman/Queue/IncomingRunner.py
downloadmailman2-b132a73f15e432eaf43310fce9196ca0c0651465.tar.gz
mailman2-b132a73f15e432eaf43310fce9196ca0c0651465.tar.xz
mailman2-b132a73f15e432eaf43310fce9196ca0c0651465.zip
This commit was manufactured by cvs2svn to create branch
'Release_2_1-maint'.
Diffstat (limited to 'Mailman/Queue/IncomingRunner.py')
-rw-r--r--Mailman/Queue/IncomingRunner.py170
1 files changed, 170 insertions, 0 deletions
diff --git a/Mailman/Queue/IncomingRunner.py b/Mailman/Queue/IncomingRunner.py
new file mode 100644
index 00000000..4a60ceb9
--- /dev/null
+++ b/Mailman/Queue/IncomingRunner.py
@@ -0,0 +1,170 @@
+# Copyright (C) 1998,1999,2000,2001,2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""Incoming queue runner."""
+
+# A typical Mailman list exposes nine aliases which point to seven different
+# wrapped scripts. E.g. for a list named `mylist', you'd have:
+#
+# mylist-bounces -> bounces (-admin is a deprecated alias)
+# mylist-confirm -> confirm
+# mylist-join -> join (-subscribe is an alias)
+# mylist-leave -> leave (-unsubscribe is an alias)
+# mylist-owner -> owner
+# mylist -> post
+# mylist-request -> request
+#
+# -request, -join, and -leave are a robot addresses; their sole purpose is to
+# process emailed commands in a Majordomo-like fashion (although the latter
+# two are hardcoded to subscription and unsubscription requests). -bounces is
+# the automated bounce processor, and all messages to list members have their
+# return address set to -bounces. If the bounce processor fails to extract a
+# bouncing member address, it can optionally forward the message on to the
+# list owners.
+#
+# -owner is for reaching a human operator with minimal list interaction
+# (i.e. no bounce processing). -confirm is another robot address which
+# processes replies to VERP-like confirmation notices.
+#
+# So delivery flow of messages look like this:
+#
+# joerandom ---> mylist ---> list members
+# | |
+# | |[bounces]
+# | mylist-bounces <---+ <-------------------------------+
+# | | |
+# | +--->[internal bounce processing] |
+# | ^ | |
+# | | | [bounce found] |
+# | [bounces *] +--->[register and discard] |
+# | | | | |
+# | | | |[*] |
+# | [list owners] |[no bounce found] | |
+# | ^ | | |
+# | | | | |
+# +-------> mylist-owner <--------+ | |
+# | | |
+# | data/owner-bounces.mbox <--[site list] <---+ |
+# | |
+# +-------> mylist-join--+ |
+# | | |
+# +------> mylist-leave--+ |
+# | | |
+# | v |
+# +-------> mylist-request |
+# | | |
+# | +---> [command processor] |
+# | | |
+# +-----> mylist-confirm ----> +---> joerandom |
+# | |
+# |[bounces] |
+# +----------------------+
+#
+# A person can send an email to the list address (for posting), the -owner
+# address (to reach the human operator), or the -confirm, -join, -leave, and
+# -request mailbots. Message to the list address are then forwarded on to the
+# list membership, with bounces directed to the -bounces address.
+#
+# [*] Messages sent to the -owner address are forwarded on to the list
+# owner/moderators. All -owner destined messages have their bounces directed
+# to the site list -bounces address, regardless of whether a human sent the
+# message or the message was crafted internally. The intention here is that
+# the site owners want to be notified when one of their list owners' addresses
+# starts bouncing (yes, the will be automated in a future release).
+#
+# Any messages to site owners has their bounces directed to a special
+# "loop-killer" address, which just dumps the message into
+# data/owners-bounces.mbox.
+#
+# Finally, message to any of the mailbots causes the requested action to be
+# performed. Results notifications are sent to the author of the message,
+# which all bounces pointing back to the -bounces address.
+
+
+import sys
+import os
+from cStringIO import StringIO
+
+from Mailman import mm_cfg
+from Mailman import Errors
+from Mailman import LockFile
+from Mailman.Queue.Runner import Runner
+from Mailman.Logging.Syslog import syslog
+
+
+
+class IncomingRunner(Runner):
+ QDIR = mm_cfg.INQUEUE_DIR
+
+ def _dispose(self, mlist, msg, msgdata):
+ # Try to get the list lock.
+ try:
+ mlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT)
+ except LockFile.TimeOutError:
+ # Oh well, try again later
+ return 1
+ # Process the message through a handler pipeline. The handler
+ # pipeline can actually come from one of three places: the message
+ # metadata, the mlist, or the global pipeline.
+ #
+ # If a message was requeued due to an uncaught exception, its metadata
+ # will contain the retry pipeline. Use this above all else.
+ # Otherwise, if the mlist has a `pipeline' attribute, it should be
+ # used. Final fallback is the global pipeline.
+ try:
+ pipeline = self._get_pipeline(mlist, msg, msgdata)
+ status = self._dopipeline(mlist, msg, msgdata, pipeline)
+ if status:
+ msgdata['pipeline'] = pipeline
+ mlist.Save()
+ return status
+ finally:
+ mlist.Unlock()
+
+ # Overridable
+ def _get_pipeline(self, mlist, msg, msgdata):
+ # We must return a copy of the list, otherwise, the first message that
+ # flows through the pipeline will empty it out!
+ return msgdata.get('pipeline',
+ getattr(mlist, 'pipeline',
+ mm_cfg.GLOBAL_PIPELINE))[:]
+
+ def _dopipeline(self, mlist, msg, msgdata, pipeline):
+ while pipeline:
+ handler = pipeline.pop(0)
+ modname = 'Mailman.Handlers.' + handler
+ __import__(modname)
+ try:
+ pid = os.getpid()
+ sys.modules[modname].process(mlist, msg, msgdata)
+ # Failsafe -- a child may have leaked through.
+ if pid <> os.getpid():
+ syslog('error', 'child process leaked thru: %s', modname)
+ 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'))
+ 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:
+ mlist.BounceMessage(msg, msgdata, e)
+ return 0
+ # We've successfully completed handling of this message
+ return 0