On Wed, 9 Jul 2003, Jason R. Mastaler wrote:

> Tim Rice <[EMAIL PROTECTED]> writes:
> 
> > Perhaps a : 
> 
> OK with me unless anyone else sees a problem with it?

See if you like this mmdf patch.
It's against 9 July 2003 CVS.

-- 
Tim Rice                                Multitalents    (707) 887-1469
[EMAIL PROTECTED]
--- tmda/TMDA/Deliver.py.old    2003-07-01 13:11:46.000000000 -0700
+++ tmda/TMDA/Deliver.py        2003-07-09 15:24:28.247200016 -0700
@@ -84,6 +84,11 @@
             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
+            self.delivery_dest = self.delivery_dest[1:].strip()
         # An mbox line begins with a slash or tilde, and does not end
         # with a slash.
         elif (firstchar == '/' or firstchar == '~') and (lastchar != '/'):
@@ -116,6 +121,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):
@@ -147,6 +166,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/TMDA/Defaults.py.old   2003-07-09 14:04:01.252560001 -0700
+++ tmda/TMDA/Defaults.py       2003-07-09 16:53:07.811760006 -0700
@@ -150,6 +150,7 @@
 # DELIVERY = "|/usr/bin/maildrop"
 # DELIVERY = "|/usr/bin/procmail ~/.procmailrc-tmda"
 # DELIVERY = "[EMAIL PROTECTED]"
+# DELIVERY = ":/var/spool/mail/jasonrm"
 #
 # No default for non-qmail users.
 if not vars().has_key('DELIVERY'):
@@ -163,7 +164,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'):
--- tmda/htdocs/config-vars.ht.old      2003-07-09 14:04:34.892560001 -0700
+++ tmda/htdocs/config-vars.ht  2003-07-09 16:50:06.266800026 -0700
@@ -1259,7 +1259,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 '='.
 <br><br>
 Default is "-"
 <dt><hr>
--- tmda/htdocs/config-filter.ht.old    2003-07-01 13:12:24.000000000 -0700
+++ tmda/htdocs/config-filter.ht        2003-07-09 15:32:39.792160019 -0700
@@ -182,6 +182,19 @@
 </tr>
 
 <tr>
+<td>mmdf</td>
+<td>
+An mmdf instruction begins with a colon.
+Please note the following restrictions below.
+</td>
+<td>
+<code>
+deliver=:/home/jason/Mailbox<br>
+</code>
+</td>
+</tr>
+
+<tr>
 <td>mbox</td>
 <td>
 An mbox instruction begins with a slash or tilde, and does not end with a
@@ -212,11 +225,11 @@
 </table>
 <br>
 
-<u>Please note the following restrictions to mbox and Maildir delivery:</u><br>
+<u>Please note the following restrictions to mmdf, mbox and Maildir delivery:</u><br>
 <ul>
 
 <li>
-TMDA will not create Maildirs or mbox files if they do not exist.  You
+TMDA will not create Maildirs, mmdf or mbox files if they do not exist.  You
 must create them prior to having TMDA deliver mail to them with
 commands like 
 <a href="http://www.qmail.org/man/man1/maildirmake.html"; TARGET="Resource Window">
@@ -225,17 +238,17 @@
 <br><br>
 
 <li>
-TMDA requires write access to any Maildir or mbox file you wish to
+TMDA requires write access to any Maildir, mmdf or mbox file you wish to
 deliver mail to.
 <br><br>
 
 <li>
-TMDA will not deliver to an mbox symlink.  Specify the path to the
+TMDA will not deliver to an mmdf or mbox symlink.  Specify the path to the
 actual mbox file instead.
 <br><br>
 
 <li>
-Do not deliver to mbox files located on an NFS filesystem.  This is
+Do not deliver to mmdf or mbox files located on an NFS filesystem.  This is
 unsafe and can corrupt your mbox file -- this applies to all MDAs, not
 just TMDA.  Use Maildir instead as it is immune to such
 problems.

Reply via email to