SF.net SVN: tmda: [2036] trunk/tmda

[email protected] Wed, 27 Sep 2006 18:02:50 -0700
Newsgroups gmane.mail.spam.tmda.cvs
Message-ID <[email protected]>
Revision: 2036
          http://svn.sourceforge.net/tmda/?rev=2036&view=rev
Author:   jasonrm
Date:     2006-09-27 18:02:44 -0700 (Wed, 27 Sep 2006)

Log Message:
-----------
First cut at the "pending queue abstraction" to allow multiple,
user-selectable formats for the TMDA pending queue.  More information
on this idea at:

http://wiki.tmda.net/TmdaOneDotTwoTodoList#head-9c4fb0cacc9f995ccfa607c65c2538db235638ce

The interface is not set in stone as of yet.  See TMDA/Queue/Queue.py,
and also OriginalQueue.py for an implementation of the current
"original" style TMDA queue.  This code should work identically to
previous versions without any changes to config files.  I've tested 
tmda-filter and tmda-pending and both seem to work fine.

One notable change is that pending messages are no longer referred to
by their filename in the logs and elsewhere.  Previously, you'd see
things like "HOLD pending 1159315215.2974.msg" in the logs.  Now that
no longer makes sense as depending on the format of the queue, the
message may or may not be stored as a flat file.  Thus, we've dropped
the '.msg' suffix, and just refer to the message as "1159315215.2974".
This can be thought of as a "mailid" that uniquely identifies the
message, no matter what kind of pending queue it's stored in.

Modified Paths:
--------------
    trunk/tmda/TMDA/ChangeLog
    trunk/tmda/TMDA/Pending.py
    trunk/tmda/TMDA/Queue/ChangeLog
    trunk/tmda/TMDA/Queue/Util.py
    trunk/tmda/TMDA/Util.py
    trunk/tmda/UPGRADE
    trunk/tmda/bin/ChangeLog
    trunk/tmda/bin/tmda-pending
    trunk/tmda/bin/tmda-rfilter

Added Paths:
-----------
    trunk/tmda/TMDA/Queue/OriginalQueue.py
    trunk/tmda/TMDA/Queue/Queue.py

Modified: trunk/tmda/TMDA/ChangeLog
===================================================================
--- trunk/tmda/TMDA/ChangeLog	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/TMDA/ChangeLog	2006-09-28 01:02:44 UTC (rev 2036)
@@ -1,3 +1,16 @@
+2006-09-27  Jason R. Mastaler  <[email protected]>
+
+	* Pending.py: Modified to use new Tmda.Queue interface.
+	
+	(Queue.cleanQueue): Removed.  Functionality moved into
+	Queue.Queue.
+
+	* Util.py (pager): Now accepts a string rather than a filepath.
+
+	(pickleit): Use 'protocol' argument as introduced in Python 2.3.
+	Also make the default protocol the new efficient
+	binary storage format compatible with Python2.3 and up.
+
 2006-09-19  Jason R. Mastaler  <[email protected]>
 
 	* AutoResponse.py: Remove arabic -> iso-8859-6 alias.  UTF-8 is

Modified: trunk/tmda/TMDA/Pending.py
===================================================================
--- trunk/tmda/TMDA/Pending.py	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/TMDA/Pending.py	2006-09-28 01:02:44 UTC (rev 2036)
@@ -26,7 +26,6 @@
 
 from email.Utils import parseaddr
 import email
-import glob
 import os
 import sys
 import time
@@ -34,7 +33,12 @@
 import Defaults
 import Errors
 import Util
+from TMDA.Queue.OriginalQueue import OriginalQueue
 
+
+Q = OriginalQueue()
+
+
 class Queue:
     """A simple pending queue."""
 
@@ -70,10 +74,9 @@
 
     def initQueue(self):
         """Initialize the queue with the given parameters (see __init__)."""
-        self.pendingdir = Defaults.PENDING_DIR
-        if not os.path.exists(self.pendingdir):
-            raise Errors.QueueError, 'Pending directory %s does not exist, exiting.' % self.pendingdir
-    
+	if not Q.exists():
+	    raise Errors.QueueError, 'Pending Queue does not exist, exiting.'
+
         # Replace any `-' in the message list with those messages provided
         # via standard input.  (Since it's pointless to call it twice,
         # it's safe to remove any subsequent occurrences in the list after
@@ -90,10 +93,7 @@
                 sys.stdin = open('/dev/tty', 'r')
 
         if not self.msgs and not wantedstdin:
-            cwd = os.getcwd()
-            os.chdir(self.pendingdir)
-            self.msgs = glob.glob('*.*.msg*')
-            os.chdir(cwd)
+            self.msgs = Q.fetch_ids()
     
         self.msgs.sort()
         if self.descending:
@@ -153,9 +153,10 @@
     def _saveCache(self):
         """Save the cache on disk."""
         if self.cache:
-            # Trim tail entries off if necessary, and then save the cache.
-            self.msgcache = self.msgcache[:Defaults.PENDING_CACHE_LEN]
-            Util.pickleit(self.msgcache, Defaults.PENDING_CACHE)
+	    # Trim tail entries off if necessary, and then save the
+	    # cache in ASCII format.
+	    self.msgcache = self.msgcache[:Defaults.PENDING_CACHE_LEN]
+            Util.pickleit(self.msgcache, Defaults.PENDING_CACHE, 0)
 
     ## Threshold (-Y and -O options)
     def checkTreshold(self, msgid):
@@ -171,38 +172,6 @@
                 return 0
         return 1
 
-    def cleanQueue(self, lifetime=None):
-        """Delete messages in the pending queue which exceed a certain
-        lifetime."""
-        # We can't use the Message class and delete method below
-        # because this would mean parsing the contents of every
-        # message regardless of whether we use PENDING_DELETE_APPEND
-        # or not.
-        self.older = 1
-        if lifetime is None:
-            self.threshold = Defaults.PENDING_LIFETIME
-        else:
-            self.threshold = lifetime
-        for msgid in self.msgs:
-            if not self.checkTreshold(msgid):
-                continue
-            # delete this message
-            msgfile = os.path.join(self.pendingdir, msgid)
-            if Defaults.PENDING_DELETE_APPEND:
-                try:
-                    msgobj = Util.msg_from_file(open(msgfile, 'r'))
-                except IOError:
-                    # in case of concurrent cleanups
-                    pass
-                else:
-                    rp = parseaddr(msgobj.get('return-path'))[1]
-                    Util.append_to_file(rp, Defaults.PENDING_DELETE_APPEND)
-            try:
-                os.unlink(msgfile)
-            except OSError:
-                # in case of concurrent cleanups
-                pass
-
     def disposeMessage(self, M):
         """Dispose the message."""
         if self.dispose is None or self.dispose == 'pass':
@@ -384,14 +353,10 @@
     confirm_accept_address = None
     def __init__(self, msgid, recipient = None):
         self.msgid = msgid
-        self.msgfile = os.path.join(Defaults.PENDING_DIR, self.msgid)
-        if not os.path.exists(self.msgfile):
-            raise Errors.MessageError, '%s not found!' % self.msgid
-        try:
-            self.msgobj = email.message_from_file(open(self.msgfile, 'r'))
-        except email.Errors.MessageError:
-            self.msgobj = Util.msg_from_file(open(self.msgfile, 'r'))
-        self.recipient = recipient
+        if not Q.find_message(self.msgid):
+	    raise Errors.MessageError, '%s not found!' % self.msgid
+        self.msgobj = Q.fetch_message(self.msgid)
+	self.recipient = recipient
         if self.recipient is None:
             self.recipient = self.msgobj.get('x-tmda-recipient')
         self.return_path = parseaddr(self.msgobj.get('return-path'))[1]
@@ -405,7 +370,7 @@
         if Defaults.PENDING_RELEASE_APPEND:
             Util.append_to_file(self.append_address,
                                 Defaults.PENDING_RELEASE_APPEND)
-        timestamp, pid, suffix = self.msgid.split('.')
+        timestamp, pid = self.msgid.split('.')
         # Remove Return-Path: to avoid duplicates.
         del self.msgobj['return-path']
         # Remove X-TMDA-Recipient:
@@ -429,7 +394,7 @@
         if Defaults.PENDING_DELETE_APPEND:
             Util.append_to_file(self.append_address,
                                 Defaults.PENDING_DELETE_APPEND)
-        os.unlink(self.msgfile)
+	Q.delete_message(self.msgid)
 
     def whitelist(self):
         """Whitelist the message sender."""
@@ -452,17 +417,12 @@
                   'PENDING_BLACKLIST_APPEND not defined!'
 
     def pager(self):
-        Util.pager(self.msgfile)
-        return ''
+        Util.pager(self.show())
+	return ''
 
     def show(self):
         """Return the string representation of a message."""
-        try:
-            return Util.msg_as_string(self.msgobj)
-        except TypeError:
-            # Re-parse using HeaderParser if Generator fails.
-            self.msgobj = Util.msg_from_file(open(self.msgfile, 'r'))
-            return Util.msg_as_string(self.msgobj)
+	return Util.msg_as_string(self.msgobj)
 
     def getDate(self):
         timestamp = self.msgid.split('.')[0]
@@ -500,7 +460,7 @@
         if not self.confirm_accept_address:
             if self.recipient:
                 import Cookie
-                (timestamp, pid, suffix) = self.msgid.split('.')
+                (timestamp, pid) = self.msgid.split('.')
                 self.confirm_accept_address =   Cookie.make_confirm_address(
                                                 self.recipient, timestamp, pid,
                                                 'accept')

Modified: trunk/tmda/TMDA/Queue/ChangeLog
===================================================================
--- trunk/tmda/TMDA/Queue/ChangeLog	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/TMDA/Queue/ChangeLog	2006-09-28 01:02:44 UTC (rev 2036)
@@ -1,3 +1,8 @@
+2006-09-27  Jason R. Mastaler  <[email protected]>
+
+	* Queue.py: new file.
+	* OriginalQueue.py: ditto.
+
 2006-09-22  Jason R. Mastaler  <[email protected]>
 
 	* Util.py: new file.

Added: trunk/tmda/TMDA/Queue/OriginalQueue.py
===================================================================
--- trunk/tmda/TMDA/Queue/OriginalQueue.py	                        (rev 0)
+++ trunk/tmda/TMDA/Queue/OriginalQueue.py	2006-09-28 01:02:44 UTC (rev 2036)
@@ -0,0 +1,143 @@
+# -*- python -*-
+#
+# Copyright (C) 2001,2002,2003,2004,2005,2006 Jason R. Mastaler <[email protected]>
+#
+# This file is part of TMDA.
+#
+# TMDA 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.  A copy of this license should
+# be included in the file COPYING.
+#
+# TMDA 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 TMDA; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Original pending queue format.  
+
+The original style TMDA queue is the only option one had under TMDA
+1.0.x and early 1.1.x releases. It's simply a single directory of
+files, one mail message stored per file, where files are named
+"mailid.msg" (e.g, 1159377144.3747.msg).  It almost looks like a
+Maildir without subdirectories.  It perhaps offers the best
+performance, but since it's a custom format, it can't be accessed and
+read with non-TMDA tools so may not be as convenient for users who
+wish to monitor the contents of their pending queue.
+"""
+
+
+from email.Utils import parseaddr
+
+import glob
+import os
+import time
+
+from TMDA import Defaults
+from TMDA import Util
+from TMDA.Queue.Queue import Queue
+
+
+
+class OriginalQueue(Queue):
+    def __init__(self):
+	Queue.__init__(self)
+	self.format = "original"
+
+
+    def exists(self):
+	if os.path.exists(Defaults.PENDING_DIR):
+	    return True
+	else:
+	    return False
+
+
+    def _create(self):
+	if not self.exists():
+	    os.makedirs(Defaults.PENDING_DIR, 0700)
+
+
+    def _convert(self):
+	pass
+
+
+    def cleanup(self):
+	if not self.exists():
+	    return
+	
+	lifetimesecs = Util.seconds(Defaults.PENDING_LIFETIME)
+	cwd = os.getcwd()
+	os.chdir(Defaults.PENDING_DIR)
+	msgs = glob.glob('*.*.msg')
+	os.chdir(cwd)
+
+        for msg in msgs:
+	    now = '%d' % time.time()
+            min_time = int(now) - int(lifetimesecs)
+            msg_time = int(msg.split('.')[0])
+            if msg_time > min_time:
+                # skip this message
+		continue
+            # delete this message
+            fpath = os.path.join(Defaults.PENDING_DIR, msg)
+            if Defaults.PENDING_DELETE_APPEND:
+                try:
+                    msgobj = Util.msg_from_file(open(fpath, 'r'))
+                except IOError:
+                    # in case of concurrent cleanups
+                    pass
+                else:
+                    rp = parseaddr(msgobj.get('return-path'))[1]
+                    Util.append_to_file(rp, Defaults.PENDING_DELETE_APPEND)
+            try:
+                os.unlink(fpath)
+            except OSError:
+                # in case of concurrent cleanups
+                pass
+
+
+    def fetch_ids(self):
+	cwd = os.getcwd()
+	os.chdir(Defaults.PENDING_DIR)
+	msgs = glob.glob('*.*.msg')
+	ids = [i.rstrip('.msg') for i in msgs]
+	os.chdir(cwd)
+	return ids
+
+
+    def insert_message(self, msg, mailid, recipient):
+	fname = mailid + ".msg"
+	# Create ~/.tmda/ and friends if necessary.
+	self._create()
+	# X-TMDA-Recipient is used by release_pending()
+	del msg['X-TMDA-Recipient']
+	msg['X-TMDA-Recipient'] = recipient
+	# Write ~/.tmda/pending/MAILID.msg
+	fcontents = Util.msg_as_string(msg)
+	fpath = os.path.join(Defaults.PENDING_DIR, fname)
+	Util.writefile(fcontents, fpath)
+	del msg['X-TMDA-Recipient']
+
+
+    def fetch_message(self, mailid):
+	fpath = os.path.join(Defaults.PENDING_DIR, mailid + '.msg')
+	msg = Util.msg_from_file(file(fpath, 'r'))
+	return msg
+
+
+    def delete_message(self, mailid):
+	fpath = os.path.join(Defaults.PENDING_DIR, mailid + '.msg')
+	os.unlink(fpath)
+
+
+    def find_message(self, mailid):
+	fpath = os.path.join(Defaults.PENDING_DIR, mailid + '.msg')
+	if os.path.exists(fpath):
+	    return True
+	else:
+	    return False

Added: trunk/tmda/TMDA/Queue/Queue.py
===================================================================
--- trunk/tmda/TMDA/Queue/Queue.py	                        (rev 0)
+++ trunk/tmda/TMDA/Queue/Queue.py	2006-09-28 01:02:44 UTC (rev 2036)
@@ -0,0 +1,108 @@
+# -*- python -*-
+#
+# Copyright (C) 2001,2002,2003,2004,2005,2006 Jason R. Mastaler <[email protected]>
+#
+# This file is part of TMDA.
+#
+# TMDA 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.  A copy of this license should
+# be included in the file COPYING.
+#
+# TMDA 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 TMDA; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Generic TMDA pending queue class.
+
+For reference, 'mailid' refers to the unique identifier of a mail
+message in the pending queue.  It's a string consisting of two numbers
+seperated by a dot, e.g, "1159383896.4198".  This infomration
+currently comes from a timestamp and the Python process id.
+"""
+
+
+class Queue:
+    def __init__(self):
+	self.format = "not defined"
+
+    # Subclasses are expected to override the following methods since
+    # their implementation is specific to the format of the queue.
+
+    def exists(self):
+	"""
+	Return true if the queue exists, otherwise False.
+	"""
+	pass
+
+
+    def _create(self):
+        """
+	Create the queue.
+	"""
+	pass
+
+
+    def _convert(self):
+	"""
+	Convert the existing queue as necessary to a different format.
+	JRM: unsure if this method will stay or not.
+	"""
+	pass
+
+
+    def cleanup(self):
+	"""
+	Delete messages from the queue that are older than
+	Defaults.PENDING_LIFETIME.
+	"""
+	pass
+
+
+    def fetch_ids(self):
+	"""
+	Return a list containing the just the ids of all messages in
+	the queue. e.g, ['1159387731.4602', '1159383896.4198']
+	"""
+	pass
+
+    
+    def insert_message(self, msg, mailid, recipient):
+	"""
+	Insert the contents of a message into the queue.
+
+	msg is an email.Message like object.
+
+	mailid (see above)
+
+	recipient is the recipient e-mail address of this message.
+	"""
+	pass
+
+
+    def fetch_message(self, mailid):
+	"""
+	Fetch the contents of a message in the queue.  Should
+	return an email.Message like object.
+	"""
+	pass
+
+
+    def delete_message(self, mailid):
+	"""
+	Delete a message in the queue.
+	"""
+	pass
+
+
+    def find_message(self, mailid):
+	"""
+	Return true if this message is in the queue, otherwise False.
+	"""
+	pass

Modified: trunk/tmda/TMDA/Queue/Util.py
===================================================================
--- trunk/tmda/TMDA/Queue/Util.py	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/TMDA/Queue/Util.py	2006-09-28 01:02:44 UTC (rev 2036)
@@ -22,40 +22,10 @@
 """General purpose (Pending Queue related) functions."""
 
 
-import os
 
-from TMDA import Errors
-from TMDA import Defaults
-from TMDA.Util import msg_as_string, writefile
-
-
-def create_pending_dir(dirpath=None):
-    """ """
-    if not dirpath:
-	dirpath = Defaults.PENDING_DIR
-    if not os.path.exists(dirpath):
-	os.makedirs(dirpath, 0700)
+# def maildirmake(dirpath):
+#     """ """
+#     os.makedirs(os.path.join(dirpath, 'cur'), 0700)
+#     os.mkdir(os.path.join(dirpath, 'new'), 0700)
+#     os.mkdir(os.path.join(dirpath, 'tmp'), 0700)
     
-
-def create_pending_msg(timestamp, pid, recip, msg):
-    """ """
-    fname = "%s.%s.msg" % (timestamp, pid)
-    # Create ~/.tmda/ and friends if necessary.
-    create_pending_dir(Defaults.PENDING_DIR)
-    # X-TMDA-Recipient is used by release_pending()
-    del msg['X-TMDA-Recipient']
-    msg['X-TMDA-Recipient'] = recip
-    # Write ~/.tmda/pending/TIMESTAMP.PID.msg
-    fcontents = msg_as_string(msg)
-    fpath = os.path.join(Defaults.PENDING_DIR, fname)
-    writefile(fcontents, fpath)
-    del msg['X-TMDA-Recipient']
-    return fname
-
-
-def maildirmake(dirpath):
-    """ """
-    os.makedirs(os.path.join(dirpath, 'cur'), 0700)
-    os.mkdir(os.path.join(dirpath, 'new'), 0700)
-    os.mkdir(os.path.join(dirpath, 'tmp'), 0700)
-    

Modified: trunk/tmda/TMDA/Util.py
===================================================================
--- trunk/tmda/TMDA/Util.py	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/TMDA/Util.py	2006-09-28 01:02:44 UTC (rev 2036)
@@ -432,21 +432,20 @@
     file.close()
 
 
-def pager(file):
-    """Display file using a UNIX text pager such as less or more."""
-    pager_list = []
+def pager(str):
+    """Display a string using a UNIX text pager such as less or more."""
     pager = os.environ.get('PAGER')
     if pager is None:
         # try to locate less or more if $PAGER is not set
         for prog in ('less', 'more'):
             path = os.popen('which ' + prog).read()
-            if path != '':
+            if path <> '':
                 pager = path
                 break
-    for arg in pager.split():
-        pager_list.append(arg)
-    pager_list.append(file)
-    os.spawnvp(os.P_WAIT, pager_list[0], pager_list)
+    try:
+	os.popen(pager, 'w').write(str)
+    except IOError:
+	return
 
 
 def normalize_sender(sender):
@@ -760,13 +759,28 @@
         return 1
 
 
-def pickleit(object, file, bin=False):
+def pickleit(object, file, proto=2):
     """Store object in a pickle file.
-    Optional bin specifies whether to use binary or text pickle format."""
+
+    Optional 'proto' specifies which data storage format to use.
+    Possible integer values include:
+
+    0 (original ASCII protocol and is backwards compatible with
+    earlier versions of Python)
+
+    1 (old binary format which is also compatible with earlier
+    versions of Python)
+
+    2 (a more effecient binary format introduced in Python 2.3)
+
+    -1 (always choose the highest protocol version available)
+
+    default is 2, since we must support Python 2.3 and above.
+    """
     tempfile.tempdir = os.path.dirname(file)
-    tmpname = tempfile.mktemp()
+    tmpname = tempfile.mkstemp()[1]
     fp = open(tmpname, 'w')
-    cPickle.dump(object, fp, bin)
+    cPickle.dump(object, fp, proto)
     fp.close()
     os.rename(tmpname, file)
     return

Modified: trunk/tmda/UPGRADE
===================================================================
--- trunk/tmda/UPGRADE	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/UPGRADE	2006-09-28 01:02:44 UTC (rev 2036)
@@ -3,6 +3,15 @@
 
 ======================================================================
 
+If you are upgrading from a release of TMDA < 1.1.6:
+
+* Mail messages in the queue are now referred to by a unique numerical
+  identifier, as discussed in TMDA/Queue/Queue.py.  For example,
+  "1159383896.4198".  For most users, this change is inconsequential
+  but is noted here nonetheless.
+
+======================================================================
+
 If you are upgrading from a release of TMDA < 1.1.4:
 
 * contrib/sample.config has been removed in favour of the

Modified: trunk/tmda/bin/ChangeLog
===================================================================
--- trunk/tmda/bin/ChangeLog	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/bin/ChangeLog	2006-09-28 01:02:44 UTC (rev 2036)
@@ -1,6 +1,6 @@
-2006-09-22  Jason R. Mastaler  <[email protected]>
+2006-09-27  Jason R. Mastaler  <[email protected]>
 
-	* tmda-rfilter (create_pending_msg): Move to TMDA.Queue.Util.
+	* tmda-rfilter: Modified to use new TMDA.Queue interface.
 	
 2004-03-25  Jason R. Mastaler  <[email protected]>
 

Modified: trunk/tmda/bin/tmda-pending
===================================================================
--- trunk/tmda/bin/tmda-pending	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/bin/tmda-pending	2006-09-28 01:02:44 UTC (rev 2036)
@@ -133,11 +133,14 @@
     (interactively operate on all pending messages)
     %(program)s 
 
+    (get a summary listing of all pending messages)
+    %(program)s -T -b
+
     (interactively operate on just these messages)
-    %(program)s 1012182077.5803.msg 1012939546.7870.msg
+    %(program)s 1012182077.5803 1012939546.7870
 
     (immediately release these messages from the pending queue)
-    %(program)s -b -r 1012182077.5803.msg 1012939546.7870.msg
+    %(program)s -b -r 1012182077.5803 1012939546.7870
 
     (immediately release any messages with `foobar' in them)
     %(program)s -b -T | grep foobar | awk '{print $1}' | %(program)s -b -r -

Modified: trunk/tmda/bin/tmda-rfilter
===================================================================
--- trunk/tmda/bin/tmda-rfilter	2006-09-25 19:19:35 UTC (rev 2035)
+++ trunk/tmda/bin/tmda-rfilter	2006-09-28 01:02:44 UTC (rev 2036)
@@ -179,7 +179,7 @@
 from TMDA import FilterParser
 from TMDA import MTA
 from TMDA import Util
-from TMDA.Queue.Util import create_pending_msg
+from TMDA.Queue.OriginalQueue import OriginalQueue
 
 from cStringIO import StringIO
 from email.Utils import parseaddr, getaddresses
@@ -200,6 +200,13 @@
 if act_as_filter:
     Defaults.DELIVERY = '_filter_'
 
+TIME = time.time()
+TIMESTAMP = str('%d' % TIME)
+MAILID = "%s.%s" % (TIMESTAMP, Defaults.PID)
+
+# A pending queue instance
+Q = OriginalQueue()
+
 # We use this MTA instance to control the fate of the message.
 mta = MTA.init(Defaults.MAIL_TRANSFER_AGENT, Defaults.DELIVERY)
 
@@ -294,7 +301,7 @@
                 vdomain_match = 1
             # .domain:prepend (wildcard)
             elif not vdomain.split('.', 1)[0]:
-                if odomain.lower().find(vdomain) != -1:
+                if odomain.lower().find(vdomain) <> -1:
                     vdomain_match = 1
             # user@domain:prepend
             else:
@@ -322,8 +329,6 @@
 subject = msgin.get('subject')
 x_primary_address = parseaddr(msgin.get('x-primary-address'))[1]
 
-pendingdir = Defaults.PENDING_DIR
-
 # Catchall variable to enable/disable auto-responses.
 auto_reply = 1
 
@@ -443,7 +448,7 @@
         ar.create()
         ar.send()
         # Optionally, record this auto-response.
-        if Defaults.MAX_AUTORESPONSES_PER_DAY != 0:
+        if Defaults.MAX_AUTORESPONSES_PER_DAY <> 0:
             ar.record()
 
 
@@ -455,7 +460,6 @@
 
 def do_default_action(action, logname, template=None):
     """Handle ACTION_* actions"""
-    disposal_time = time.time()
     if action in ('bounce', 'reject'):
         logit('BOUNCE', logname)
         bouncegen('bounce', template=template)
@@ -507,8 +511,7 @@
         do_default_action(Defaults.ACTION_INVALID_CONFIRMATION.lower(),
                           'action_invalid_confirmation',
                           'bounce_invalid_confirmation.txt')
-    confirmed_filename = '%s.%s.msg' % (confirm_timestamp, confirm_pid)
-    confirmed_filepath = os.path.join(pendingdir, confirmed_filename)
+    confirmed_mailid = '%s.%s' % (confirm_timestamp, confirm_pid)
     # pre-confirmation
     if confirm_action == 'accept':
         new_confirm_hmac = Cookie.confirmationmac(confirm_timestamp,
@@ -519,13 +522,13 @@
             do_default_action(Defaults.ACTION_INVALID_CONFIRMATION.lower(),
                               'action_invalid_confirmation',
                               'bounce_invalid_confirmation.txt')
-        elif not (os.path.exists(confirmed_filepath)):
+        elif not (Q.find_message(confirmed_mailid)):
             do_default_action(Defaults.ACTION_MISSING_PENDING.lower(),
                               'action_missing_pending',
                               'bounce_missing_pending.txt')
         else:
-            msg = Util.msg_from_file(open(confirmed_filepath, 'r'))
-            logit("CONFIRM", "accept " + confirmed_filename)
+            msg = Q.fetch_message(confirmed_mailid)
+	    logit("CONFIRM", "accept " + confirmed_mailid)
             # Optionally append the sender's address to a file and/or DB.
             if Defaults.CONFIRM_APPEND or Defaults.DB_CONFIRM_APPEND:
                 confirm_append_addr = Util.confirm_append_address(
@@ -533,10 +536,10 @@
                     parseaddr(msg.get('return-path'))[1])
                 if not confirm_append_addr:
                     raise IOError, \
-                          confirmed_filepath + ' has no Return-Path header!'
+                          confirmed_mailid + ' has no Return-Path header!'
                 if Defaults.CONFIRM_APPEND:
                     if Util.append_to_file(confirm_append_addr,
-                                           Defaults.CONFIRM_APPEND) != 0:
+                                           Defaults.CONFIRM_APPEND) <> 0:
                         logit('CONFIRM_APPEND', Defaults.CONFIRM_APPEND)
                 if Defaults.DB_CONFIRM_APPEND and Defaults.DB_CONNECTION:
                     _username = Defaults.USERNAME.lower()
@@ -573,7 +576,7 @@
         else:
             logit("OK", "good_confirm_done_cookie")
             try:
-                os.unlink(confirmed_filepath)
+                Q.delete_message(confirmed_mailid)
             except OSError:
                 pass
             # Remove X-TMDA-Confirm-Done: since it's only used
@@ -595,7 +598,7 @@
                           'bounce_fail_dated.txt')
     # Accept the message only if the address has not expired, and the
     # HMAC is valid.
-    if datemac != Cookie.datemac(cookie_date): 
+    if datemac <> Cookie.datemac(cookie_date): 
         do_default_action(Defaults.ACTION_FAIL_DATED.lower(),
                           'action_fail_dated',
                           'bounce_fail_dated.txt')
@@ -647,7 +650,6 @@
     if discard:
         mta.stop()
     # Common variables.
-    now = time.time()
     recipient_address = globals().get('recipient_address')
     recipient_local, recipient_domain = recipient_address.split('@', 1)
     envelope_sender = globals().get('envelope_sender')
@@ -664,7 +666,7 @@
     if Defaults.DATED_TEMPLATE_VARS:
         dated_timeout = Util.format_timeout(Defaults.DATED_TIMEOUT)
         dated_expire_date = time.asctime(time.gmtime
-                                         (now +
+                                         (TIME +
                                           Util.seconds(Defaults.DATED_TIMEOUT)))
         dated_recipient_address = Cookie.make_dated_address(recipient_address)
     # Optional 'sender' address variables.
@@ -682,11 +684,10 @@
             templatefile = template
         else:
             templatefile = 'confirm_request.txt'
-        timestamp = str('%d' %now)
-        pid = Defaults.PID
+
         confirm_accept_address = Cookie.make_confirm_address(recipient_address,
-                                                             timestamp,
-                                                             pid,
+                                                             TIMESTAMP,
+                                                             Defaults.PID,
                                                              'accept')
         if Defaults.CGI_URL:
             # create the url for tmda-cgi release.
@@ -696,24 +697,23 @@
                                                      os.geteuid(),
                                                      recipient_address,
                                                      Cookie.make_confirm_cookie(
-                    timestamp,
-                    pid,
+                    TIMESTAMP,
+                    Defaults.PID,
                     'accept'
                     ))
             else:
                 # include the current euid and release cookie.
                 confirm_accept_url = '%s?%s.%s' %(Defaults.CGI_URL, os.geteuid(),
-                                                  Cookie.make_confirm_cookie(timestamp,
-                                                                             pid,
+                                                  Cookie.make_confirm_cookie(TIMESTAMP,
+                                                                             Defaults.PID,
                                                                              'accept'))
-        pending_message = create_pending_msg(timestamp, pid, recipient_address, msgin)
+	Q.insert_message(msgin, MAILID, recipient_address)
     elif mode == 'hold':
-        pending_message = create_pending_msg(str('%d' % now), Defaults.PID, 
-					     recipient_address, msgin)
+        Q.insert_message(msgin, MAILID, recipient_address)
         # Don't send anything for silently held messages
         if Defaults.CONFIRM_CC:
             send_cc(Defaults.CONFIRM_CC)
-        logit("HOLD", "pending " + pending_message)
+        logit("HOLD", "pending " + MAILID)
         mta.stop()
     # Create the confirm message and then send it.
     bounce_message = Util.maketext(templatefile, vars())
@@ -725,7 +725,7 @@
     elif mode == 'request':
         if Defaults.CONFIRM_CC:
             send_cc(Defaults.CONFIRM_CC)
-        logit("CONFIRM", "pending " + pending_message)
+        logit("CONFIRM", "pending " + MAILID)
         send_bounce(bounce_message, mode)
         mta.stop()     
 
@@ -735,15 +735,11 @@
 ######
 
 def main():
-    # Possibly clean the pending queue?
-    if Defaults.PENDING_CLEANUP_ODDS <> 0 and \
-           os.path.exists(Defaults.PENDING_DIR):
-        from random import random
-        if random() < float(Defaults.PENDING_CLEANUP_ODDS):
-            from TMDA import Pending
-            q = Pending.Queue()
-            q.initQueue()
-            q.cleanQueue()
+    # cleanup the pending queue
+    if Defaults.PENDING_CLEANUP_ODDS <> 0:
+	from random import random
+	if random() < float(Defaults.PENDING_CLEANUP_ODDS):
+	    Q.cleanup()
     # Get the cookie type and value by parsing the extension address.
     ext = address_extension
     cookie_type = cookie_value = None
@@ -762,7 +758,7 @@
     sender_dict = { envelope_sender: None }
     confirm_append_address = Util.confirm_append_address(x_primary_address,
                                                          envelope_sender)
-    if confirm_append_address and confirm_append_address != envelope_sender:
+    if confirm_append_address and confirm_append_address <> envelope_sender:
         sender_dict[confirm_append_address] = None
     from_list = getaddresses(msgin.get_all('from', []))
     replyto_list = getaddresses(msgin.get_all('reply-to', []))


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.