CVS: tmda/TMDA Defaults.py,1.184,1.185 Deliver.py,1.16,1.17

"Jason R. Mastaler" <[email protected]>
Newsgroups gmane.mail.spam.tmda.cvs
Message-ID <[email protected]>
Update of /cvsroot/tmda/tmda/TMDA
In directory sc8-pr-cvs1:/tmp/cvs-serv13319/TMDA

Modified Files:
	Defaults.py Deliver.py 
Log Message:
Add support for MMDF-style mailbox delivery courtesy of Tim Rice.


Index: Defaults.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Defaults.py,v
retrieving revision 1.184
retrieving revision 1.185
diff -u -r1.184 -r1.185
--- Defaults.py	11 Jul 2003 23:02:59 -0000	1.184
+++ Defaults.py	23 Jul 2003 19:52:47 -0000	1.185
@@ -147,6 +147,8 @@
 # DELIVERY = "~/Maildir/"
 # DELIVERY = "~/Mailbox"
 # DELIVERY = "/var/mail/jasonrm"
+# DELIVERY = ":~/Mailbox"
+# DELIVERY = ":/var/spool/mail/jasonrm"
 # DELIVERY = "|/usr/bin/maildrop"
 # DELIVERY = "|/usr/bin/procmail ~/.procmailrc-tmda"
 # DELIVERY = "[email protected]"
@@ -163,7 +165,7 @@
 # A single character which specifies the separator between user names
 # and address extensions (e.g, user-ext).
 # The default under qmail is `-', while the default for Sendmail and
-# friends is likely `+'.
+# friends is likely `+'. The default for MMDF is '='.
 #
 # Default is "-"
 if not vars().has_key('RECIPIENT_DELIMITER'):

Index: Deliver.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Deliver.py,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- Deliver.py	19 Jul 2003 04:29:26 -0000	1.16
+++ Deliver.py	23 Jul 2003 19:52:47 -0000	1.17
@@ -85,6 +85,12 @@
             self.delivery_dest = self.option
             if firstchar == '&':
                 self.delivery_dest = self.delivery_dest[1:].strip()
+        # An mmdf line begins with a : 
+        elif firstchar == ':':
+            self.delivery_type = 'mmdf'
+            self.delivery_dest = self.option[1:].strip()
+            if self.delivery_dest.startswith('~'):
+                self.delivery_dest = os.path.expanduser(self.delivery_dest)
         # An mbox line begins with a slash or tilde, and does not end
         # with a slash.
         elif (firstchar == '/' or firstchar == '~') and (lastchar != '/'):
@@ -120,6 +126,20 @@
         elif type == 'forward':
             # don't wrap headers, don't escape From, don't add From_ line
             self.__deliver_forward(Util.msg_as_string(self.msg), dest)
+        elif type == 'mmdf':
+            # Ensure destination path exists.
+            if not os.path.exists(dest):
+                raise Errors.DeliveryError, \
+                      'Destination "%s" does not exist!' % dest
+            # Refuse to deliver to an mmdf if it's a symlink, to
+            # prevent symlink attacks.
+            elif os.path.islink(dest):
+                raise Errors.DeliveryError, \
+                      'Destination "%s" is a symlink!' % dest
+            else:
+                # don't wrap headers, escape From, add From_ line
+                self.__deliver_mmdf(Util.msg_as_string(self.msg, 0, 1, 1),
+                                    dest)
         elif type == 'mbox':
             # Ensure destination path exists.
             if not os.path.exists(dest):
@@ -153,6 +173,61 @@
         """Forward message to address, preserving the existing Return-Path."""
         Util.sendmail(message, address, self.env_sender)
         
+    def __deliver_mmdf(self, message, mmdf):
+        """Reliably deliver a mail message into an mmdf file.
+
+        Basicly a copy of __deliver_mbox():
+        Just make sure each message is surrounded by "\1\1\1\1\n"
+        """
+        try:
+	    # When orig_length is None, we haven't opened the file yet.
+            orig_length = None
+            # Open the mmdf file.
+            fp = open(mmdf, 'rb+')
+            lock_file(fp)
+            status_old = os.fstat(fp.fileno())
+            # Check if it _is_ an mmdf file; mmdf files must start
+            # with "\1\1\1\1\n" in their first line, or are 0-length files.
+            fp.seek(0, 0)                # seek to start
+            first_line = fp.readline()
+            if first_line != '' and first_line[:5] != '\1\1\1\1\n':
+                # Not an mmdf file; abort here.
+                unlock_file(fp)
+                fp.close()
+                raise Errors.DeliveryError, \
+                      'Destination "%s" is not an mmdf file!' % mmdf
+            fp.seek(0, 2)                # seek to end
+            orig_length = fp.tell()      # save original length
+            fp.write('\1\1\1\1\n')
+            # Add a trailing newline if last line incomplete.
+            if message[-1] != '\n':
+                message = message + '\n'
+            # Write the message.
+            fp.write(message)
+            # Add a trailing blank line.
+            fp.write('\n')
+            fp.write('\1\1\1\1\n')
+            fp.flush()
+            os.fsync(fp.fileno())
+            # Unlock and close the file.
+            status_new = os.fstat(fp.fileno())
+            unlock_file(fp)
+            fp.close()
+            # Reset atime.
+            os.utime(mmdf, (status_old[stat.ST_ATIME], status_new[stat.ST_MTIME]))
+        except IOError, txt:
+            try:
+                if not fp.closed and not orig_length is None:
+		    # If the file was opened and we know how long it was,
+		    # try to truncate it back to that length.
+                    fp.truncate(orig_length)
+                unlock_file(fp)
+                fp.close()
+            except:
+                pass
+            raise Errors.DeliveryError, \
+                  'Failure writing message to mmdf file "%s" (%s)' % (mmdf, txt)
+
     def __deliver_mbox(self, message, mbox):
         """Reliably deliver a mail message into an mboxrd-format mbox file.
 

_______________________________________
tmda-cvs mailing list
http://tmda.net/lists/listinfo/tmda-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.