Flush SMTP output buffer before "delay" in an ACL; add control =
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 5 Feb 2007 12:35:46 +0000 (12:35 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 5 Feb 2007 12:35:46 +0000 (12:35 +0000)
no_delay_flush to disable this behaviour.

doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/acl.c
src/src/globals.c
src/src/globals.h
test/confs/0552 [new file with mode: 0644]
test/log/0552 [new file with mode: 0644]
test/scripts/0000-Basic/0552 [new file with mode: 0644]

index 4cb842c6dcbf9a70f50cc6738d68256f887605d0..6179dec3efcbec615571d4eabdd8ffe9ab11ea9b 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.467 2007/01/31 16:52:12 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.468 2007/02/05 12:35:46 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -71,6 +71,8 @@ PH/13 Added ${rfc2047d: to decoded RFC 2047 strings.
 
 PH/14 Added log_selector = +pid.
 
 
 PH/14 Added log_selector = +pid.
 
+PH/15 Flush SMTP output before delaying, unless control=no_delay_flush is set.
+
 
 Exim version 4.66
 -----------------
 
 Exim version 4.66
 -----------------
index ccd5989cbcd2704556554a73c30d1af57c7a3ac9..ae6c48991bf07a2bee3df9396b699088c557a4c6 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.134 2007/01/31 16:52:12 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.135 2007/02/05 12:35:46 ph10 Exp $
 
 New Features in Exim
 --------------------
 
 New Features in Exim
 --------------------
@@ -232,6 +232,10 @@ Version 4.67
     id to be added to every log line, in square brackets, immediately after the
     time and date.
 
     id to be added to every log line, in square brackets, immediately after the
     time and date.
 
+11. Exim has been modified so that it flushes SMTP output before implementing
+    a delay in an ACL. This behaviour can be disabled by obeying control =
+    no_delay_flush at some earlier point.
+
 
 Version 4.66
 ------------
 
 Version 4.66
 ------------
index 3e06cdf303a15474dcd3ccf597659e25cd7fb9c2..517063635fc77e224615e880e0bcce50d89c7108 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.69 2007/01/30 11:45:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.70 2007/02/05 12:35:46 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -187,7 +187,8 @@ enum {
   CONTROL_FAKEDEFER,
   CONTROL_FAKEREJECT,
   CONTROL_NO_MULTILINE,
   CONTROL_FAKEDEFER,
   CONTROL_FAKEREJECT,
   CONTROL_NO_MULTILINE,
-  CONTROL_NO_PIPELINING
+  CONTROL_NO_PIPELINING,
+  CONTROL_NO_DELAY_FLUSH
 };
 
 /* ACL control names; keep in step with the table above! This list is used for
 };
 
 /* ACL control names; keep in step with the table above! This list is used for
@@ -219,9 +220,10 @@ static uschar *controls[] = {
   US"fakereject",
   US"no_multiline",
   US"no_pipelining",
   US"fakereject",
   US"no_multiline",
   US"no_pipelining",
+  US"no_delay_flush"
 };
 
 };
 
-/* Flags to indicate for which conditions /modifiers a string expansion is done
+/* Flags to indicate for which conditions/modifiers a string expansion is done
 at the outer level. In the other cases, expansion already occurs in the
 checking functions. */
 
 at the outer level. In the other cases, expansion already occurs in the
 checking functions. */
 
@@ -593,6 +595,9 @@ static unsigned int control_forbids[] = {
     (1<<ACL_WHERE_NOTSMTP_START),
 
   (1<<ACL_WHERE_NOTSMTP)|                          /* no_pipelining */
     (1<<ACL_WHERE_NOTSMTP_START),
 
   (1<<ACL_WHERE_NOTSMTP)|                          /* no_pipelining */
+    (1<<ACL_WHERE_NOTSMTP_START),
+
+  (1<<ACL_WHERE_NOTSMTP)|                          /* no_delay_flush */
     (1<<ACL_WHERE_NOTSMTP_START)
 };
 
     (1<<ACL_WHERE_NOTSMTP_START)
 };
 
@@ -616,6 +621,7 @@ static control_def controls_list[] = {
   { US"caselower_local_part",    CONTROL_CASELOWER_LOCAL_PART, FALSE },
   { US"enforce_sync",            CONTROL_ENFORCE_SYNC, FALSE },
   { US"freeze",                  CONTROL_FREEZE, TRUE },
   { US"caselower_local_part",    CONTROL_CASELOWER_LOCAL_PART, FALSE },
   { US"enforce_sync",            CONTROL_ENFORCE_SYNC, FALSE },
   { US"freeze",                  CONTROL_FREEZE, TRUE },
+  { US"no_delay_flush",          CONTROL_NO_DELAY_FLUSH, FALSE },
   { US"no_enforce_sync",         CONTROL_NO_ENFORCE_SYNC, FALSE },
   { US"no_multiline_responses",  CONTROL_NO_MULTILINE, FALSE },
   { US"no_pipelining",           CONTROL_NO_PIPELINING, FALSE },
   { US"no_enforce_sync",         CONTROL_NO_ENFORCE_SYNC, FALSE },
   { US"no_multiline_responses",  CONTROL_NO_MULTILINE, FALSE },
   { US"no_pipelining",           CONTROL_NO_PIPELINING, FALSE },
@@ -2605,6 +2611,10 @@ for (; cb != NULL; cb = cb->next)
       pipelining_enable = FALSE;
       break;
 
       pipelining_enable = FALSE;
       break;
 
+      case CONTROL_NO_DELAY_FLUSH:
+      disable_delay_flush = TRUE;
+      break;
+
       case CONTROL_FAKEDEFER:
       case CONTROL_FAKEREJECT:
       fake_response = (control_type == CONTROL_FAKEDEFER) ? DEFER : FAIL;
       case CONTROL_FAKEDEFER:
       case CONTROL_FAKEREJECT:
       fake_response = (control_type == CONTROL_FAKEDEFER) ? DEFER : FAIL;
@@ -2720,13 +2730,18 @@ for (; cb != NULL; cb = cb->next)
         can't. The poll() function does not do the right thing, and in any case
         it is not always available.
 
         can't. The poll() function does not do the right thing, and in any case
         it is not always available.
 
-        NOTE: If ever this state of affairs changes, remember that we may be
+        NOTE 1: If ever this state of affairs changes, remember that we may be
         dealing with stdin/stdout here, in addition to TCP/IP connections.
         dealing with stdin/stdout here, in addition to TCP/IP connections.
-        Whatever is done must work in both cases. To detected the stdin/stdout
-        case, check for smtp_in or smtp_out being NULL. */
+        Also, delays may be specified for non-SMTP input, where smtp_out and
+        smtp_in will be NULL. Whatever is done must work in all cases.
+
+        NOTE 2: The added feature of flushing the output before a delay must
+        apply only to SMTP input. Hence the test for smtp_out being non-NULL.
+        */
 
         else
           {
 
         else
           {
+          if (smtp_out != NULL && !disable_delay_flush) fflush(smtp_out);
           while (delay > 0) delay = sleep(delay);
           }
         }
           while (delay > 0) delay = sleep(delay);
           }
         }
index b030c7f7b4a43add87d51239f8e606bd3f14a522..b3bbd7faffe0f9c7f57bb22cd3af12bc258a6946 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.67 2007/01/31 16:52:12 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.68 2007/02/05 12:35:46 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -499,6 +499,7 @@ int     demime_errorlevel      = 0;
 int     demime_ok              = 0;
 uschar *demime_reason          = NULL;
 #endif
 int     demime_ok              = 0;
 uschar *demime_reason          = NULL;
 #endif
+BOOL    disable_delay_flush    = FALSE;
 #ifdef ENABLE_DISABLE_FSYNC
 BOOL    disable_fsync          = FALSE;
 #endif
 #ifdef ENABLE_DISABLE_FSYNC
 BOOL    disable_fsync          = FALSE;
 #endif
index 70227d592c301ac64db09b49df7b3775bbaff1bd..570e4c87b8a05108b6461f222125b2d5fbc62400 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.47 2007/01/30 15:10:59 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.48 2007/02/05 12:35:46 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -278,6 +278,7 @@ extern int     demime_errorlevel;      /* Severity of MIME error */
 extern int     demime_ok;              /* Nonzero if message has been demimed */
 extern uschar *demime_reason;          /* Reason for broken MIME container */
 #endif
 extern int     demime_ok;              /* Nonzero if message has been demimed */
 extern uschar *demime_reason;          /* Reason for broken MIME container */
 #endif
+extern BOOL    disable_delay_flush;    /* Don't flush before "delay" in ACL */
 #ifdef ENABLE_DISABLE_FSYNC
 extern BOOL    disable_fsync;          /* Not for normal use */
 #endif
 #ifdef ENABLE_DISABLE_FSYNC
 extern BOOL    disable_fsync;          /* Not for normal use */
 #endif
diff --git a/test/confs/0552 b/test/confs/0552
new file mode 100644 (file)
index 0000000..3ce7751
--- /dev/null
@@ -0,0 +1,66 @@
+# Exim test configuration 0552
+
+DDF=
+SERVER=
+
+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/SERVER%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+# ----- Main settings -----
+
+acl_not_smtp = check_not
+acl_smtp_connect = check_connect
+acl_smtp_rcpt = check_rcpt
+
+queue_only
+
+# ----- ACL -----
+
+begin ACL
+
+check_connect:
+  accept DDF
+
+check_rcpt:
+  accept delay = 1s
+
+check_not:
+  accept delay = 1s
+         logwrite = Accept non-SMTP
+
+
+# ----- Routers -----
+
+begin routers
+
+r1:
+  driver = accept
+  transport = t1
+
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = smtp
+  port = PORT_D
+  hosts = 127.0.0.1
+  allow_localhost
+  command_timeout = 2s
+
+
+# ----- Retry -----
+
+begin retry
+
+* * F,1d,1s
+
+
+# End
diff --git a/test/log/0552 b/test/log/0552
new file mode 100644 (file)
index 0000000..e5a1fd8
--- /dev/null
@@ -0,0 +1,19 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 Accept non-SMTP
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx1@test.ex R=r1 T=t1 defer (dd): Connection timed out: SMTP timeout while connected to 127.0.0.1 [127.0.0.1] after MAIL FROM:<CALLER@myhost.test.ex> SIZE=1310
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx2@test.ex R=r1 T=t1 defer (dd): Connection timed out: SMTP timeout while connected to 127.0.0.1 [127.0.0.1] after MAIL FROM:<CALLER@myhost.test.ex> SIZE=1310
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx3@test.ex R=r1 T=t1 defer (dd): Connection timed out: SMTP timeout while connected to 127.0.0.1 [127.0.0.1] after MAIL FROM:<CALLER@myhost.test.ex> SIZE=1310
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+1999-03-02 09:44:33 Start queue run: pid=pppp -qf
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userx1@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1]
+1999-03-02 09:44:33 10HmaX-0005vi-00 -> userx2@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1]
+1999-03-02 09:44:33 10HmaX-0005vi-00 -> userx3@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1]
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qf
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
+1999-03-02 09:44:33 SMTP connection from localhost (myhost.test.ex) [127.0.0.1] lost while reading message data (header)
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex
diff --git a/test/scripts/0000-Basic/0552 b/test/scripts/0000-Basic/0552
new file mode 100644 (file)
index 0000000..1958dbe
--- /dev/null
@@ -0,0 +1,20 @@
+# autoflush for delay
+need_ipv4
+#
+# Put a message on the queue (queue_only is set); this tests that a
+# non-SMTP delay still works.
+exim userx1@test.ex userx2@test.ex userx3@test.ex
+****
+# This daemon is "old-style", without the flush
+exim -DSERVER=server -DDDF=control=no_delay_flush -bd -oX PORT_D
+****
+exim -qf
+****
+killdaemon
+# This daemon should flush before delaying
+exim -DSERVER=server -bd -oX PORT_D
+****
+exim -qf
+****
+killdaemon
+no_msglog_check