diff options
Diffstat (limited to 'Mailman/OutgoingQueue.py')
| -rw-r--r-- | Mailman/OutgoingQueue.py | 198 |
1 files changed, 0 insertions, 198 deletions
diff --git a/Mailman/OutgoingQueue.py b/Mailman/OutgoingQueue.py deleted file mode 100644 index 6ad5cf5ba..000000000 --- a/Mailman/OutgoingQueue.py +++ /dev/null @@ -1,198 +0,0 @@ -# Copyright (C) 1998 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. - -"""Queue up posts if the SMTP connection fails.""" -# -# messages are queued before a delivery attempt takes place -# this ensures that should the system fail for some reason, -# the run_queue process will make delivery attempts later. -# -# so q files have 2 possible states - those that are queued because -# they are currently being delivered by the initial delivery attempt -# and those that are queued because the first delivery attempt has -# failed. the former state is indicated by the fact that the filename -# is setuid. all queue entries in the latter state are not setuid and -# have data in them. Since there's no way in python to create a file -# that is setuid at creation time, all files that are empty are -# considered to be in the first state (after the open call but before -# the chmod call). - -# -# protection from multiple processQueue procedures occuring -# simultaneously is enforced by setting a lock file forcing -# only one such process to happen at a time. -# - -import sys -import os -import time -import stat -import marshal -import errno -import mm_cfg -import Utils - -# We need the version of tempfile.py from Python 1.5.2 because it has -# provisions for uniquifying filenames in concurrent children after a fork. -# If not using Python 1.5.2's version, let's get our copy of the new file. -import tempfile -if not hasattr(tempfile, '_pid'): - from Mailman.pythonlib import tempfile -assert hasattr(tempfile, '_pid') - -TEMPLATE = "mm_q." -# -# multiple prcesses with different uids can write and/or -# defer q entries. with the queue directory setgid to mailman -# and writable by group mailman, having the QF_MODE set to 0660 -# should enable any process with gid mailman to read, write, rename, -# or unlink the file -# -QF_MODE = 0660 - -# -# how long can a q entry possibly be in the -# active state? -# -MAX_ACTIVE = 7200 # 2 hours - - -# processQueue is called from cron/run_queue, which manages the lockfile -# -# find all the files that are deferred queue entries and all the files that -# have been in an active state for too long and attempt a delivery -# -def processQueue(): - files = os.listdir(mm_cfg.DATA_DIR) - for file in files: - # - # does it look like a queue entry? - # - if TEMPLATE != file[:len(TEMPLATE)]: - continue - full_fname = os.path.join(mm_cfg.DATA_DIR, file) - # - # we need to stat the file if it still exists (atomically, we can't - # just use use os.path.exists then stat it. if it doesn't exist, it's - # been dequeued since we saw it in the directory listing - # - try: - st = os.stat(full_fname) - except os.error, (code, msg): - if code == errno.ENOENT: - # file does not exist, it's already been dequeued - continue - else: - Utils.reraise() - # - # if the file is not a deferred queue message, we check to see if the - # creation time was too long ago and process it anyway. If the - # creation time was recent, leave it alone as it's probably being - # delivered by another process anyway - # - if (not isDeferred(full_fname, st) and - st[stat.ST_CTIME] > (time.time() - MAX_ACTIVE)): - # then - continue - try: - f = open(full_fname,"r") - recip,sender,text = marshal.load(f) - f.close() - Utils.TrySMTPDelivery(recip,sender,text,full_fname) - failure = None - except (# marshal.load() failed - EOFError, ValueError, TypeError, - # open() or close() failed - IOError): - failure = sys.exc_info() - - if failure: - # Should we risk moving the queue file out of the way? That - # might cause another exception, if the permissions are - # wrong enough... - t, v = failure[0], failure[1] - from Logging.StampedLogger import StampedLogger - l = StampedLogger("error", "processQueue", immediate=1) - l.write("Processing of queue file %s failed:\n" % full_fname) - l.write("\t %s" % t) - if v: - l.write(' / %s' % v) - l.write('\n') - l.flush() - - -# -# this function is used by any process that -# attempts to deliver a message for the first time -# so the entry is set with the SUID bit. With all these -# concurrent processes calling this function, we can't quite -# trust mktemp() to generate a unique filename, and with the -# possibility of a q entry lasting longer than the pid generation -# cycle on the system we can't quite trust os.getpid() to return -# a unique filename either. but if we use getpid() in the -# template, then mktemp should always return a unique filename. -# -def enqueueMessage(the_sender, recip, text): - tempfile.tempdir = mm_cfg.DATA_DIR - tempfile.template = "%s%d." % (TEMPLATE, os.getpid()) - fname = tempfile.mktemp() - # - # open the file so that it is setuid upon creation - # - f = Utils.open_ex(fname, "a+", -1, QF_MODE | stat.S_ISUID) - marshal.dump((recip,the_sender,text),f) - f.close() - return fname - - -# -# is this queue entry a deferred one? -# -def isDeferred(q_entry, st=None): - if st is None: - st = os.stat(q_entry) - if st[stat.ST_MODE] & stat.S_ISUID: - return 0 - else: - return 1 - - -# -# given the full path to a q_entry, set the -# status to deferred if it is not -# already in that state. this function must work -# on entries already in a deferred state. -# this function may only be called by the process -# that called enqueueMessage(), since it uses chmod -# -def deferMessage(q_entry): - if not isDeferred(q_entry): - os.chmod(q_entry, QF_MODE) - - -# -# given the full path to a q_entry -# remove it from the queue -# -def dequeueMessage(q_entry): - try: - os.unlink(q_entry) - except os.error, (code, msg): - if code == errno.ENOENT: - # file does not exist, probably because the lock was stolen - pass - else: - Utils.reraise() |
