logo       
Google Custom Search
    AddThis Social Bookmark Button
-->

CVS: tmda/TMDA ChangeLog,1.169,1.170 Deliver.py,1.3,1.4: msg#00123

Subject: CVS: tmda/TMDA ChangeLog,1.169,1.170 Deliver.py,1.3,1.4
Update of /cvsroot/tmda/tmda/TMDA
In directory usw-pr-cvs1:/tmp/cvs-serv31352/TMDA

Modified Files:
        ChangeLog Deliver.py 
Log Message:
Add local delivery to qmail-style Maildirs.

Implementation based upon deliver_maildir() from Charles Cazabon's
getmail program.


Index: ChangeLog
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/ChangeLog,v
retrieving revision 1.169
retrieving revision 1.170
diff -u -r1.169 -r1.170
--- ChangeLog   27 Feb 2002 22:21:54 -0000      1.169
+++ ChangeLog   27 Feb 2002 23:05:34 -0000      1.170
@@ -1,5 +1,8 @@
 2002-02-27  Jason R. Mastaler  <jasonrm@xxxxxxxxxxxxxxxxxxxxxxxxxx>
 
+       * Deliver.py (Deliver.__deliver_maildir): New method to reliably
+       deliver a message into a qmail-style Maildir.
+
        * Util.py (pipecmd): Include getmail copyright for borrowed GPL
        code.
 

Index: Deliver.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Deliver.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Deliver.py  27 Feb 2002 22:01:42 -0000      1.3
+++ Deliver.py  27 Feb 2002 23:05:34 -0000      1.4
@@ -23,12 +23,22 @@
 
 
 import os
+import signal
+import socket
+import stat
+import time
 
 import Defaults
 import Errors
 import Util
 
 
+def alarm_handler(signum, frame):
+    """Handle an alarm."""
+    print 'Signal handler called with signal', signum
+    raise IOError, "Couldn't open device!"
+
+
 class Deliver:
     def __init__(self, headers, body, delivery_option):
         """
@@ -97,7 +107,11 @@
         elif type == 'mbox':
             self.__deliver_mbox(self.message, dest)
         elif type == 'maildir':
-            self.__deliver_maildir(self.message, dest)
+            if os.path.exists(dest):
+                self.__deliver_maildir(self.message, dest)
+            else:
+                raise Errors.DeliveryError, \
+                      'Destination "%s" does not exist!' % dest
 
     def __deliver_program(self, message, program):
         """Deliver message to /bin/sh -c program."""
@@ -113,6 +127,69 @@
               'mbox delivery not yet implemented!'
 
     def __deliver_maildir(self, message, maildir):
-        """ """
-        raise Errors.DeliveryError, \
-              'Maildir delivery not yet implemented!'
+        """Reliably deliver a mail message into a Maildir.
+
+        See <URL:http://www.qmail.org/man/man5/maildir.html>
+
+        Based on code from getmail
+        <URL:http://www.qcc.sk.ca/~charlesc/software/getmail-2.0/>
+        Copyright (C) 2001 Charles Cazabon, and licensed under the GNU
+        General Public License version 2.
+        """
+        # e.g, 1014754642.51195.aguirre.la.mastaler.com
+        filename = '%s.%s.%s' % (int(time.time()), Defaults.PID,
+                                 socket.gethostname())
+        # Set a 24-hour alarm for this delivery.
+        signal.signal(signal.SIGALRM, alarm_handler)
+        signal.alarm(24 * 60 * 60)
+
+        dir_tmp = os.path.join(maildir, 'tmp')
+        dir_new = os.path.join(maildir, 'new')
+        if not (os.path.isdir(dir_tmp) and os.path.isdir(dir_new)):
+            raise Errors.DeliveryError, 'not a Maildir! (%s)' % maildir
+
+        fname_tmp = os.path.join(dir_tmp, filename)
+        fname_new = os.path.join(dir_new, filename)
+
+        # File must not already exist.
+        if os.path.exists(fname_tmp):
+            raise Errors.DeliveryError, fname_tmp + 'already exists!'
+        if os.path.exists(fname_new):
+            raise Errors.DeliveryError, fname_new + 'already exists!'
+
+        # Get user & group of maildir.
+        s_maildir = os.stat(maildir)
+        maildir_owner = s_maildir[stat.ST_UID]
+        maildir_group = s_maildir[stat.ST_GID]
+
+        # Open file to write.
+        try:
+            fp = open(fname_tmp, 'wb')
+            try:
+                os.chown(fname_tmp, maildir_owner, maildir_group)
+            except OSError:
+                # Not running as root, can't chown file.
+                pass
+            os.chmod(fname_tmp, 0600)
+            fp.write(message)
+            fp.flush()
+            os.fsync(fp.fileno())
+            fp.close()
+        except IOError:
+            raise Errors.DeliveryError, 'Failure writing file ' + fname_tmp
+
+        # Move message file from Maildir/tmp to Maildir/new
+        try:
+            os.link(fname_tmp, fname_new)
+            os.unlink(fname_tmp)
+        except OSError:
+            try:
+                os.unlink(fname_tmp)
+            except:
+                pass
+            raise Errors.DeliveryError, 'failure renaming "%s" to "%s"' \
+                   % (fname_tmp, fname_new)
+
+        # Cancel the alarm.
+        signal.alarm(0)
+        signal.signal(signal.SIGALRM, signal.SIG_DFL)

_______________________________________________
tmda-cvs mailing list
http://libertine.org/lists/listinfo/tmda-cvs



<Prev in Thread] Current Thread [Next in Thread>