Fix problem with maildir delivery into a folder that is excluded from
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 25 Apr 2006 14:02:29 +0000 (14:02 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 25 Apr 2006 14:02:29 +0000 (14:02 +0000)
quota calculations.

doc/doc-txt/ChangeLog
src/src/transports/appendfile.c
test/README
test/confs/5009 [new file with mode: 0644]
test/log/5009 [new file with mode: 0644]
test/runtest
test/scripts/5000-maildir/5009 [new file with mode: 0644]
test/stdout/5009 [new file with mode: 0644]

index d2ba436ee68d82f1ce1d57d2f7387f1e45916a25..24233428557dd81cd507b6f7aa53dd34417e8753 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.347 2006/04/25 10:44:57 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.348 2006/04/25 14:02:29 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -42,6 +42,14 @@ PH/07 The appendfile transport was creating MBX lock files with a fixed mode
 
 PH/08 Applied small patch from the Sieve maintainer.
 
+PH/09 If maildir_quota_directory_regex was set to exclude (say) the .Trash
+      folder from quota calculations, a direct delivery into this folder messed
+      up the contents of the maildirsize file. This was because the regex was
+      used only to exclude .Trash (or whatever) when the size of the mailbox
+      was calculated. There was no check that a delivery was happening into an
+      excluded directory. This bug has been fixed by ignoring all quota
+      processing for deliveries into excluded directories.
+
 
 Exim version 4.61
 -----------------
index 0e024f51b3bfb573a45277ff1bd1320bcebc4ec0..d7f2705448b17501046bbd45f135c5b12e5e4082 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.16 2006/04/25 10:06:30 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.17 2006/04/25 14:02:30 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1226,6 +1226,7 @@ uschar *filecount_msg = US"";
 uschar *path;
 struct utimbuf times;
 struct timeval msg_tv;
+BOOL disable_quota = FALSE;
 BOOL isdirectory = FALSE;
 BOOL isfifo = FALSE;
 BOOL wait_for_tick = FALSE;
@@ -2170,7 +2171,7 @@ else
     const uschar *error;
     int offset;
 
-    /* Compile the regex if there is one */
+    /* Compile the regex if there is one. */
 
     if (ob->quota_size_regex != NULL)
       {
@@ -2183,11 +2184,8 @@ else
           ob->quota_size_regex);
         return FALSE;
         }
-      else
-        {
-        DEBUG(D_transport) debug_printf("using regex for file sizes: %s\n",
-          ob->quota_size_regex);
-        }
+      DEBUG(D_transport) debug_printf("using regex for file sizes: %s\n",
+        ob->quota_size_regex);
       }
 
     /* Use an explicitly configured directory if set */
@@ -2263,6 +2261,8 @@ else
 
     if (ob->maildir_dir_regex != NULL)
       {
+      int check_path_len = Ustrlen(check_path);
+
       dir_regex = pcre_compile(CS ob->maildir_dir_regex, PCRE_COPT,
         (const char **)&error, &offset, NULL);
       if (dir_regex == NULL)
@@ -2272,11 +2272,27 @@ else
           ob->maildir_dir_regex);
         return FALSE;
         }
-      else
+
+      DEBUG(D_transport)
+        debug_printf("using regex for maildir directory selection: %s\n",
+          ob->maildir_dir_regex);
+
+      /* Check to see if we are delivering into an ignored directory, that is,
+      if the delivery path starts with the quota check path, and the rest
+      of the deliver path matches the regex; if so, set a flag to disable quota
+      checking and maildirsize updating. */
+
+      if (Ustrncmp(path, check_path, check_path_len) == 0)
         {
-        DEBUG(D_transport)
-          debug_printf("using regex for maildir directory selection: %s\n",
-            ob->maildir_dir_regex);
+        uschar *s = path + check_path_len;
+        while (*s == '/') s++;
+        s = (*s == 0)? US "new" : string_sprintf("%s/new", s);
+        if (pcre_exec(dir_regex, NULL, CS s, Ustrlen(s), 0, 0, NULL, 0) < 0)
+          {
+          disable_quota = TRUE;
+          DEBUG(D_transport) debug_printf("delivery directory does not match "
+            "maildir_quota_directory_regex: disabling quota\n");
+          }
         }
       }
 
@@ -2287,6 +2303,7 @@ else
 
 /*  if (???? || ob->quota_value > 0) */
 
+    if (!disable_quota)
       {
       off_t size;
       int filecount;
@@ -2327,7 +2344,8 @@ else
   count. Note that ob->quota_filecount_value cannot be set without
   ob->quota_value being set. */
 
-  if ((ob->quota_value > 0 || THRESHOLD_CHECK) &&
+  if (!disable_quota &&
+      (ob->quota_value > 0 || THRESHOLD_CHECK) &&
       (mailbox_size < 0 ||
         (mailbox_filecount < 0 && ob->quota_filecount_value > 0)))
     {
@@ -2605,7 +2623,7 @@ with this message if quota_is_inclusive is set; if it is not set, the check
 is for the mailbox already being over quota (i.e. the current message is not
 included in the check). */
 
-if (ob->quota_value > 0)
+if (!disable_quota && ob->quota_value > 0)
   {
   DEBUG(D_transport)
     {
@@ -2775,22 +2793,25 @@ added headers. */
 message_size = transport_count;
 
 /* If using a maildir++ quota file, add this message's size to it, and
-close the file descriptor. */
+close the file descriptor, except when the quota has been disabled because we
+are delivering into an uncounted folder. */
 
 #ifdef SUPPORT_MAILDIR
-if (yield == OK && maildirsize_fd >= 0)
-  maildir_record_length(maildirsize_fd, message_size);
-
-maildir_save_errno = errno;       /* Preserve errno while closing the file */
-(void)close(maildirsize_fd);
-errno = maildir_save_errno;
+if (!disable_quota)
+  {
+  if (yield == OK && maildirsize_fd >= 0)
+    maildir_record_length(maildirsize_fd, message_size);
+  maildir_save_errno = errno;    /* Preserve errno while closing the file */
+  (void)close(maildirsize_fd);
+  errno = maildir_save_errno;
+  }
 #endif  /* SUPPORT_MAILDIR */
 
 /* If there is a quota warning threshold and we are have crossed it with this
 message, set the SPECIAL_WARN flag in the address, to cause a warning message
 to be sent. */
 
-if (THRESHOLD_CHECK)
+if (!disable_quota && THRESHOLD_CHECK)
   {
   off_t threshold = ob->quota_warn_threshold_value;
   if (ob->quota_warn_threshold_is_percent)
index 13284ab2c5e66fe849a8182daa32a6c1b29f7487..004477e70dd9037c49df5d0976782a76efb1632b 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/test/README,v 1.2 2006/02/10 16:29:20 ph10 Exp $
+$Cambridge: exim/test/README,v 1.3 2006/04/25 14:02:30 ph10 Exp $
 
 EXPORTABLE EXIM TEST SUITE
 --------------------------
@@ -705,8 +705,9 @@ deliveries because on different systems the processes may terminate in a
 different order.
 
 
-A number of standard file management commands are recognized. These are chmod,
-chown, ln, ls, du, mkdir, mkfifo, and touch. Some are run as root using "sudo".
+A number of standard file management commands are recognized. These are cat,
+chmod, chown, cp, ln, ls, du, mkdir, mkfifo, rm, rmdir, and touch. Some are run
+as root using "sudo".
 
 
 Commands with input
diff --git a/test/confs/5009 b/test/confs/5009
new file mode 100644 (file)
index 0000000..a2f673d
--- /dev/null
@@ -0,0 +1,49 @@
+# Exim test configuration 5009
+
+SUB=
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+rfc1413_query_timeout = 0s
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+
+# ----- Main settings -----
+
+qualify_domain = test.ex
+
+
+# ----- Routers -----
+
+begin routers
+
+r1:
+  driver = accept
+  transport = t1
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = appendfile
+  directory = DIR/test-mail/SUB
+  user = CALLER
+  maildir_format
+  maildir_use_size_file
+  maildir_quota_directory_regex = ^(?:cur|new|\.(?!Trash).*)$
+  quota = 1M
+
+
+# ----- Retry -----
+
+begin retry
+
+* * F,1d,1d
+
+
+# End
diff --git a/test/log/5009 b/test/log/5009
new file mode 100644 (file)
index 0000000..7d70439
--- /dev/null
@@ -0,0 +1,9 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userx <userx@test.ex> R=r1 T=t1
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userx <userx@test.ex> R=r1 T=t1
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => userx <userx@test.ex> R=r1 T=t1
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
index d6b3fac7f7dbfc3c5988796d9fee49ea6cb25a0f..91b64e8e970910d00ffe5331cc26e98f7c06c833 100755 (executable)
@@ -1,6 +1,6 @@
 #! /usr/bin/perl -w
 
-# $Cambridge: exim/test/runtest,v 1.8 2006/04/20 15:34:25 ph10 Exp $
+# $Cambridge: exim/test/runtest,v 1.9 2006/04/25 14:02:30 ph10 Exp $
 
 ###############################################################################
 # This is the controlling script for the "new" test suite for Exim. It should #
@@ -613,7 +613,7 @@ while(<IN>)
   s/\b\d+\.H\d+P\d+\b/dddddddddd.HddddddPddddd/;
 
   # Maildirsize data
-  if (/^\d+S,\d+C\s*$/)
+  while (/^\d+S,\d+C\s*$/)
     {
     print MUNGED;
     while (<IN>)
@@ -623,6 +623,7 @@ while(<IN>)
       }
     last if !defined $_;
     }
+  last if !defined $_;
 
 
   # ======== Output from the "fd" program about open descriptors ========
diff --git a/test/scripts/5000-maildir/5009 b/test/scripts/5000-maildir/5009
new file mode 100644 (file)
index 0000000..1a2e5fc
--- /dev/null
@@ -0,0 +1,19 @@
+# maildirsize with maildir_quota_directory_regex
+#
+exim -odi userx@test.ex
+Test message
+****
+cat DIR/test-mail/maildirsize >>test-stdout
+mkdir test-mail/.Sub
+touch test-mail/.Sub/maildirfolder
+exim -DSUB=.Sub -odi userx@test.ex
+Test message
+****
+cat DIR/test-mail/maildirsize >>test-stdout
+mkdir test-mail/.Trash
+touch test-mail/.Trash/maildirfolder
+exim -DSUB=.Trash -odi userx@test.ex
+Test message
+****
+cat DIR/test-mail/maildirsize >>test-stdout
+no_message_check
diff --git a/test/stdout/5009 b/test/stdout/5009
new file mode 100644 (file)
index 0000000..65318c4
--- /dev/null
@@ -0,0 +1,11 @@
+1048576S,0C
+ddd d
+ddd d
+1048576S,0C
+ddd d
+ddd d
+ddd d
+1048576S,0C
+ddd d
+ddd d
+ddd d