Merge branch 'patch-3' of https://github.com/bes-internal/exim into master_dmarc_doc
authorTodd Lyons <tlyons@exim.org>
Mon, 30 Sep 2013 19:55:44 +0000 (12:55 -0700)
committerTodd Lyons <tlyons@exim.org>
Mon, 30 Sep 2013 19:56:57 +0000 (12:56 -0700)
25 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
doc/doc-txt/experimental-spec.txt
src/ACKNOWLEDGMENTS
src/src/EDITME
src/src/config.h.defaults
src/src/deliver.c
src/src/exim.c
src/src/expand.c
src/src/globals.c
src/src/globals.h
src/src/structs.h
src/src/transport.c
src/src/transports/smtp.c
src/src/transports/smtp.h
src/util/ratelimit.pl
test/.gitignore
test/Makefile.in
test/confs/5700 [new file with mode: 0644]
test/log/5700 [new file with mode: 0644]
test/paniclog/5700 [new file with mode: 0644]
test/scripts/5700-tpt-post-dlv-action/5700 [new file with mode: 0644]
test/scripts/5700-tpt-post-dlv-action/REQUIRES [new file with mode: 0644]
test/stderr/5700 [new file with mode: 0644]
test/stdout/5700 [new file with mode: 0644]

index 85d4316..0f603e4 100644 (file)
@@ -232,6 +232,13 @@ TL/11 Bugzilla 1382 - Option ldap_require_cert overrides start_tls
       using NULL (global ldap config) instead of ldap handle (per
       session). Bug diagnosis and testing by alxgomz.
 
+TL/12 Enhanced documentation in the ratelimit.pl script provided in
+      the src/util/ subdirectory.
+
+TL/13 Bug 1301 - Imported transport SQL logging patch from Axel Rau
+      renamed to Transport Post Delivery Action by Jeremy Harris, as
+                       EXPERIMENTAL_TPDA.
+
 
 Exim version 4.80.1
 -------------------
index 2b038e3..9c8b9df 100644 (file)
@@ -154,6 +154,9 @@ Version 4.82
 24. New ${hexquote:..string..} expansion operator converts non-printable
     characters in the string to \xNN form.
 
+25. Experimental TPDA (Transport Post Delivery Action) function added.
+    Patch provided by Axel Rau.
+
 
 Version 4.80
 ------------
index f9be19c..271ab0b 100644 (file)
@@ -761,7 +761,7 @@ mean, refer to the DMARC website above.  Valid strings are:
                 sender domain.
   o nofrom      Unable to determine the domain of the sender.
   o temperror   Library error or dns error.
-  o off         The DMARC check was disable for this email.
+  o off         The DMARC check was disabled for this email.
 
 You can prefix each string with an exclamation mark to invert its
 meaning, for example "!accept" will match all results but
@@ -846,6 +846,90 @@ b. Configure, somewhere before the DATA ACL, the control option to
 
 
 
+Transport post-delivery actions
+--------------------------------------------------------------
+
+An arbitrary per-transport string can be expanded on successful delivery,
+and (for SMTP transports) a second string on deferrals caused by a host error.
+This feature may be used, for example, to write exim internal log information
+(not available otherwise) into a database.
+
+In order to use the feature, you must set
+
+EXPERIMENTAL_TPDA=yes
+
+in your Local/Makefile
+
+and define the expandable strings in the runtime config file, to
+be executed at end of delivery.
+
+Additionally, there are 6 more variables, available at end of
+delivery:
+
+tpda_delivery_ip             IP of host, which has accepted delivery
+tpda_delivery_port           Port of remote host which has accepted delivery
+tpda_delivery_fqdn           FQDN of host, which has accepted delivery
+tpda_delivery_local_part     local part of address being delivered
+tpda_delivery_domain         domain part of address being delivered
+tpda_delivery_confirmation   SMTP confirmation message
+
+In case of a deferral caused by a host-error:
+tpda_defer_errno             Error number
+tpda_defer_errstr            Error string possibly containing more details
+
+The $router_name and $transport_name variables are also usable.
+
+
+To take action after successful deliveries, set the following option
+on any transport of interest.
+
+tpda_delivery_action
+
+An example might look like:
+
+tpda_delivery_action = \
+${lookup pgsql {SELECT * FROM record_Delivery( \
+    '${quote_pgsql:$sender_address_domain}',\
+    '${quote_pgsql:${lc:$sender_address_local_part}}', \
+    '${quote_pgsql:$tpda_delivery_domain}', \
+    '${quote_pgsql:${lc:$tpda_delivery_local_part}}', \
+    '${quote_pgsql:$tpda_delivery_ip}', \
+    '${quote_pgsql:${lc:$tpda_delivery_fqdn}}', \
+    '${quote_pgsql:$message_exim_id}')}}
+
+The string is expanded after the delivery completes and any
+side-effects will happen.  The result is then discarded.
+Note that for complex operations an ACL expansion can be used.
+
+
+In order to log host deferrals, add the following option to an SMTP
+transport:
+
+tpda_host_defer_action
+
+This is a private option of the SMTP transport. It is intended to
+log failures of remote hosts. It is executed only when exim has
+attempted to deliver a message to a remote host and failed due to
+an error which doesn't seem to be related to the individual
+message, sender, or recipient address.
+See section 45.2 of the exim documentation for more details on how
+this is determined.
+
+Example:
+
+tpda_host_defer_action = \
+${lookup mysql {insert into delivlog set \
+    msgid = '${quote_mysql:$message_exim_id}', \
+    senderlp = '${quote_mysql:${lc:$sender_address_local_part}}', \
+    senderdom = '${quote_mysql:$sender_address_domain}', \
+    delivlp = '${quote_mysql:${lc:$tpda_delivery_local_part}}', \
+    delivdom = '${quote_mysql:$tpda_delivery_domain}', \
+    delivip = '${quote_mysql:$tpda_delivery_ip}', \
+    delivport = '${quote_mysql:$tpda_delivery_port}', \
+    delivfqdn = '${quote_mysql:$tpda_delivery_fqdn}', \
+    deliverrno = '${quote_mysql:$tpda_defer_errno}', \
+    deliverrstr = '${quote_mysql:$tpda_defer_errstr}' \
+    }}
 
 --------------------------------------------------------------
 End of file
index 0611b1f..ea9076a 100644 (file)
@@ -221,6 +221,7 @@ Chris Liddiard            Fix for bug in exiqsumm
 Chris Lightfoot           Patch for -restore-times in exim_lock
 Edgar Lovecraft           Patch for ${str2b64:
 Torsten Luettgert         Suggested patch for proper integer overflow detection
+Todd Lyons                Patch to add DMARC support using OpenDMARC libs/tools
 David Madole              Patch for SPA forced expansion failure bug
 Lars Mainka               Patch for OpenSSL crl collections
 Andrey Malyshev           Patch for $address_data after redirection bug
@@ -253,6 +254,7 @@ Eric Parusel              Patch for tls_remember_esmtp
 Gaige Paulsen             Amended Darwin config files
 Richard Premdas           Patch for PAM buglet
 Jason Pyeron              Suggested patch for ignoring Sendmail's -O option
+Axel Rau                  Patch for Transport Post Delivery sql logging
 Mark Rigby-Jones          Patch for race condition during MBX locking
 Robert Roselius           Patch for OpenSSL workaround for bad clients
 Larry Rosenman            OpenUNIX config files
index e29c1eb..1db70f7 100644 (file)
@@ -469,6 +469,10 @@ EXIM_MONITOR=eximon.bin
 # Uncomment the following line to add Per-Recipient-Data-Response support.
 # EXPERIMENTAL_PRDR=yes
 
+# Uncomment the following line to support Transport post-delivery actions,
+# eg. for logging to a database.
+# EXPERIMENTAL_TPDA=yes
+
 
 ###############################################################################
 #                 THESE ARE THINGS YOU MIGHT WANT TO SPECIFY                  #
index 1594f68..bf7ac63 100644 (file)
@@ -170,6 +170,7 @@ it's a default value. */
 #define EXPERIMENTAL_PRDR
 #define EXPERIMENTAL_SPF
 #define EXPERIMENTAL_SRS
+#define EXPERIMENTAL_TPDA
 
 /* For developers */
 #define WANT_DEEPER_PRINTF_CHECKS
index 23e63d5..bc6a69f 100644 (file)
@@ -695,6 +695,15 @@ the log line, and reset the store afterwards. Remote deliveries should always
 have a pointer to the host item that succeeded; local deliveries can have a
 pointer to a single host item in their host list, for use by the transport. */
 
+#ifdef EXPERIMENTAL_TPDA
+  tpda_delivery_ip = NULL;     /* presume no successful remote delivery */
+  tpda_delivery_port = 0;
+  tpda_delivery_fqdn = NULL;
+  tpda_delivery_local_part = NULL;
+  tpda_delivery_domain = NULL;
+  tpda_delivery_confirmation = NULL;
+#endif
+
 s = reset_point = store_get(size);
 
 log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE);
@@ -741,7 +750,12 @@ if ((log_extra_selector & LX_delivery_size) != 0)
 if (addr->transport->info->local)
   {
   if (addr->host_list != NULL)
+    {
     s = string_append(s, &size, &ptr, 2, US" H=", addr->host_list->name);
+    #ifdef EXPERIMENTAL_TPDA
+      tpda_delivery_fqdn = addr->host_list->name;
+    #endif
+    }
   if (addr->shadow_message != NULL)
     s = string_cat(s, &size, &ptr, addr->shadow_message,
       Ustrlen(addr->shadow_message));
@@ -760,6 +774,15 @@ else
         addr->host_used->port));
     if (continue_sequence > 1)
       s = string_cat(s, &size, &ptr, US"*", 1);
+
+    #ifdef EXPERIMENTAL_TPDA
+    tpda_delivery_ip =           addr->host_used->address;
+    tpda_delivery_port =         addr->host_used->port;
+    tpda_delivery_fqdn =         addr->host_used->name;
+    tpda_delivery_local_part =   addr->local_part;
+    tpda_delivery_domain =       addr->domain;
+    tpda_delivery_confirmation = addr->message;
+    #endif
     }
 
   #ifdef SUPPORT_TLS
@@ -827,6 +850,23 @@ store we used to build the line after writing it. */
 
 s[ptr] = 0;
 log_write(0, flags, "%s", s);
+
+#ifdef EXPERIMENTAL_TPDA
+if (addr->transport->tpda_delivery_action)
+  {
+  DEBUG(D_deliver)
+    debug_printf("  TPDA(Delivery): tpda_deliver_action=|%s| tpda_delivery_IP=%s\n",
+      addr->transport->tpda_delivery_action, tpda_delivery_ip);
+
+  router_name =    addr->router->name;
+  transport_name = addr->transport->name;
+  if (!expand_string(addr->transport->tpda_delivery_action) && *expand_string_message)
+    log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand tpda_deliver_action in %s: %s\n",
+      transport_name, expand_string_message);
+  router_name = NULL;
+  transport_name = NULL;
+  }
+#endif
 store_reset(reset_point);
 return;
 }
index 8ab0456..c5053ba 100644 (file)
@@ -825,6 +825,9 @@ fprintf(f, "Support for:");
 #ifdef EXPERIMENTAL_PRDR
   fprintf(f, " Experimental_PRDR");
 #endif
+#ifdef EXPERIMENTAL_TPDA
+  fprintf(f, " Experimental_TPDA");
+#endif
 fprintf(f, "\n");
 
 fprintf(f, "Lookups (built-in):");
index edef45d..a22ee2a 100644 (file)
@@ -677,6 +677,16 @@ static var_entry var_table[] = {
   { "tod_logfile",         vtype_todlf,       NULL },
   { "tod_zone",            vtype_todzone,     NULL },
   { "tod_zulu",            vtype_todzulu,     NULL },
+#ifdef EXPERIMENTAL_TPDA
+  { "tpda_defer_errno",     vtype_int,         &tpda_defer_errno },
+  { "tpda_defer_errstr",    vtype_stringptr,   &tpda_defer_errstr },
+  { "tpda_delivery_confirmation", vtype_stringptr,   &tpda_delivery_confirmation },
+  { "tpda_delivery_domain", vtype_stringptr,   &tpda_delivery_domain },
+  { "tpda_delivery_fqdn",   vtype_stringptr,   &tpda_delivery_fqdn },
+  { "tpda_delivery_ip",     vtype_stringptr,   &tpda_delivery_ip },
+  { "tpda_delivery_local_part",vtype_stringptr,&tpda_delivery_local_part },
+  { "tpda_delivery_port",   vtype_int,         &tpda_delivery_port },
+#endif
   { "transport_name",      vtype_stringptr,   &transport_name },
   { "value",               vtype_stringptr,   &lookup_value },
   { "version_number",      vtype_stringptr,   &version_string },
index 05bb0ae..d4589cd 100644 (file)
@@ -1280,6 +1280,17 @@ int     thismessage_size_limit = 0;
 int     timeout_frozen_after   = 0;
 BOOL    timestamps_utc         = FALSE;
 
+#ifdef EXPERIMENTAL_TPDA
+int     tpda_defer_errno        = 0;
+uschar *tpda_defer_errstr       = NULL;
+uschar *tpda_delivery_ip        = NULL;
+int     tpda_delivery_port      = 0;
+uschar *tpda_delivery_fqdn      = NULL;
+uschar *tpda_delivery_local_part= NULL;
+uschar *tpda_delivery_domain    = NULL;
+uschar *tpda_delivery_confirmation = NULL;
+#endif
+
 transport_instance  *transports = NULL;
 
 transport_instance  transport_defaults = {
index 2cc1688..104b5fa 100644 (file)
@@ -834,6 +834,18 @@ extern int     test_harness_load_avg;  /* For use when testing */
 extern int     thismessage_size_limit; /* Limit for this message */
 extern int     timeout_frozen_after;   /* Max time to keep frozen messages */
 extern BOOL    timestamps_utc;         /* Use UTC for all times */
+
+#ifdef EXPERIMENTAL_TPDA
+extern int     tpda_defer_errno;        /* error number set when a remote delivery is deferred with a host error */
+extern uschar *tpda_defer_errstr;       /* error string set when a remote delivery is deferred with a host error */
+extern uschar *tpda_delivery_ip;        /* IP of host, which has accepted delivery */
+extern int     tpda_delivery_port;       /* port of host, which has accepted delivery */
+extern uschar *tpda_delivery_fqdn;      /* FQDN of host, which has accepted delivery */
+extern uschar *tpda_delivery_local_part;/* local part of address being delivered */
+extern uschar *tpda_delivery_domain;    /* domain part of address being delivered */
+extern uschar *tpda_delivery_confirmation; /* SMTP confirmation message */
+#endif
+
 extern uschar *transport_name;         /* Name of transport last started */
 extern int     transport_count;        /* Count of bytes transported */
 extern int     transport_newlines;     /* Accurate count of number of newline chars transported */
index 53aa210..baf9a0f 100644 (file)
@@ -184,6 +184,9 @@ typedef struct transport_instance {
   BOOL    log_fail_output;
   BOOL    log_defer_output;
   BOOL    retry_use_local_part;   /* Defaults true for local, false for remote */
+#ifdef EXPERIMENTAL_TPDA
+  uschar  *tpda_delivery_action;  /* String to expand on success */
+#endif
 } transport_instance;
 
 
index 7dd1afb..d2540be 100644 (file)
@@ -94,6 +94,10 @@ optionlist optionlist_transports[] = {
                  (void *)offsetof(transport_instance, shadow_condition) },
   { "shadow_transport", opt_stringptr|opt_public,
                  (void *)offsetof(transport_instance, shadow) },
+#ifdef EXPERIMENTAL_TPDA
+  { "tpda_delivery_action",opt_stringptr | opt_public,
+                 (void *)offsetof(transport_instance, tpda_delivery_action) },
+#endif
   { "transport_filter", opt_stringptr|opt_public,
                  (void *)offsetof(transport_instance, filter_command) },
   { "transport_filter_timeout", opt_time|opt_public,
index 25cc549..9918f31 100644 (file)
@@ -156,6 +156,10 @@ optionlist smtp_transport_options[] = {
   { "tls_verify_certificates", opt_stringptr,
       (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) }
 #endif
+#ifdef EXPERIMENTAL_TPDA
+ ,{ "tpda_host_defer_action", opt_stringptr,
+      (void *)offsetof(smtp_transport_options_block, tpda_host_defer_action) },
+#endif
 };
 
 /* Size of the options list. An extern variable has to be used so that its
@@ -233,6 +237,9 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   NULL,                /* dkim_sign_headers */
   NULL                 /* dkim_strict */
 #endif
+#ifdef EXPERIMENTAL_TPDA
+ ,NULL                 /* tpda_host_defer_action */
+#endif
 };
 
 
@@ -577,6 +584,59 @@ else
 
 
 
+#ifdef EXPERIMENTAL_TPDA
+/*************************************************
+*   Post-defer action                            *
+*************************************************/
+
+/* This expands an arbitrary per-transport string.
+   It might, for example, be used to write to the database log.
+
+Arguments:
+  ob                    transport options block
+  addr                  the address item containing error information
+  host                  the current host
+
+Returns:   nothing
+*/
+
+static void
+tpda_deferred(smtp_transport_options_block *ob, address_item *addr, host_item *host)
+{
+uschar *action = ob->tpda_host_defer_action;
+if (!action)
+       return;
+
+tpda_delivery_ip =         string_copy(host->address);
+tpda_delivery_port =       (host->port == PORT_NONE)? 25 : host->port;
+tpda_delivery_fqdn =       string_copy(host->name);
+tpda_delivery_local_part = string_copy(addr->local_part);
+tpda_delivery_domain =     string_copy(addr->domain);
+tpda_defer_errno =         addr->basic_errno;
+
+tpda_defer_errstr = addr->message
+  ? addr->basic_errno > 0
+    ? string_sprintf("%s: %s", addr->message, strerror(addr->basic_errno))
+    : string_copy(addr->message)
+  : addr->basic_errno > 0
+    ? string_copy(strerror(addr->basic_errno))
+    : NULL;
+
+DEBUG(D_transport)
+  debug_printf("  TPDA(host defer): tpda_host_defer_action=|%s| tpda_delivery_IP=%s\n",
+    action, tpda_delivery_ip);
+
+router_name =    addr->router->name;
+transport_name = addr->transport->name;
+if (!expand_string(action) && *expand_string_message)
+  log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand tpda_defer_action in %s: %s\n",
+    transport_name, expand_string_message);
+router_name = transport_name = NULL;
+}
+#endif
+
+
+
 /*************************************************
 *           Synchronize SMTP responses           *
 *************************************************/
@@ -976,7 +1036,7 @@ smtp_auth(uschar *buffer, unsigned bufsize, address_item *addrlist, host_item *h
       FALSE);
     return DEFER;
     }
-  
+
   return OK;
 }
 
@@ -1912,7 +1972,12 @@ if (!ok) ok = TRUE; else
 
     /* Set up confirmation if needed - applies only to SMTP */
 
-    if ((log_extra_selector & LX_smtp_confirmation) != 0 && !lmtp)
+    if (
+        #ifndef EXPERIMENTAL_TPDA
+          (log_extra_selector & LX_smtp_confirmation) != 0 &&
+        #endif
+          !lmtp
+       )
       {
       uschar *s = string_printing(buffer);
       conf = (s == buffer)? (uschar *)string_copy(s) : s;
@@ -1991,12 +2056,12 @@ if (!ok) ok = TRUE; else
         the transport name. See lots of comments in deliver.c about the reasons
         for the complications when homonyms are involved. Just carry on after
         write error, as it may prove possible to update the spool file later. */
-  
+
         if (testflag(addr, af_homonym))
           sprintf(CS buffer, "%.500s/%s\n", addr->unique + 3, tblock->name);
         else
           sprintf(CS buffer, "%.500s\n", addr->unique);
-  
+
         DEBUG(D_deliver) debug_printf("journalling %s", buffer);
         len = Ustrlen(CS buffer);
         if (write(journal_fd, buffer, len) != len)
@@ -2033,7 +2098,7 @@ if (!ok) ok = TRUE; else
             sprintf(CS buffer, "%.500s/%s\n", addr->unique + 3, tblock->name);
           else
             sprintf(CS buffer, "%.500s\n", addr->unique);
-  
+
           DEBUG(D_deliver) debug_printf("journalling(PRDR) %s", buffer);
           len = Ustrlen(CS buffer);
           if (write(journal_fd, buffer, len) != len)
@@ -3051,6 +3116,11 @@ for (cutoff_retry = 0; expired &&
                          first_addr->basic_errno != ERRNO_TLSFAILURE)
         write_logs(first_addr, host);
 
+      #ifdef EXPERIMENTAL_TPDA
+      if (rc == DEFER)
+        tpda_deferred(ob, first_addr, host);
+      #endif
+
       /* If STARTTLS was accepted, but there was a failure in setting up the
       TLS session (usually a certificate screwup), and the host is not in
       hosts_require_tls, and tls_tempfail_tryclear is true, try again, with
@@ -3073,6 +3143,10 @@ for (cutoff_retry = 0; expired &&
           expanded_hosts != NULL, &message_defer, TRUE);
         if (rc == DEFER && first_addr->basic_errno != ERRNO_AUTHFAIL)
           write_logs(first_addr, host);
+        #ifdef EXPERIMENTAL_TPDA
+        if (rc == DEFER)
+          tpda_deferred(ob, first_addr, host);
+        #endif
         }
       #endif
       }
index 8e85294..0d88016 100644 (file)
@@ -73,6 +73,9 @@ typedef struct {
   uschar *dkim_sign_headers;
   uschar *dkim_strict;
   #endif
+  #ifdef EXPERIMENTAL_TPDA
+  uschar *tpda_host_defer_action;
+  #endif
 } smtp_transport_options_block;
 
 /* Data for reading the private options. */
index 749125c..d7fd43a 100644 (file)
@@ -4,47 +4,69 @@ use strict;
 
 sub usage () {
   print <<END;
-usage: ratelimit.pl <period> <regex> logfile
+usage: ratelimit.pl [options] <period> <regex> <logfile>
 
 The aim of this script is to compute clients' peak sending rates
 from an Exim log file, using the same formula as Exim's ratelimit
 ACL condition. This is so that you can get an idea of a reasonable
 limit setting before you deploy the restrictions.
 
-This script isn't perfectly accurate, because the time stamps in
-Exim's log files are only accurate to a second whereas internally
-Exim computes sender rates to the accuracy of your computer's clock
-(typically 10ms).
-
-The log files to be processed can be specified on the command line
-after the other arguments; if no filenames are specified the script
-will read from stdin.
-
-The first command line argument is the smoothing period, as defined by
-the documentation for the ratelimit ACL condition. The second argumetn
-is a regular expression.
-
-Each line is matched against the regular expression. Lines that do not
-match are ignored. The regex may contain 0, 1, or 2 () capturing
-sub-expressions.
-
-If there are no () sub-expressions, then every line that matches is
-used to compute a single rate. Its maximum value is reported when the
-script finishes.
-
-If there is one () sub-expression, then the text matched by the
-sub-expression is used to identify a rate lookup key, similar to the
-lookup key used by the ratelimit ACL condition. For example, you might
-write a regex to match the client IP address, or the authenticated
-username. Separate rates are computed for each different client and
-the maximum rate for each client is reported when the script finishes.
-
-If there are two () sub-expressions, then the text matched by the
-first sub-expression is used to identify a rate lookup key as above,
-and the second is used to match the message size recorded in the log
-line, e.g. " S=(\\d+) ". In this case the byte rate is computed instead
-of the message rate, similar to the per_byte option of the ratelimit
-ACL condition.
+options:
+
+-d          Show debugging information to stderr
+-p          Show progress of parse the log to stderr
+
+<period>    The smoothing period in seconds, as defined by the
+            documentation for the ratelimit ACL condition.
+
+            This script isn't perfectly accurate, because the time
+            stamps in Exim's log files are only accurate to a second
+            whereas internally Exim computes sender rates to the
+            accuracy of your computer's clock (typically 10ms).
+
+<regex>     The second argument is a regular expression.
+
+            Each line is matched against the regular expression.
+            Lines that do not match are ignored. The regex may
+            contain 0, 1, or 2 () capturing sub-expressions.
+
+            If there are no () sub-expressions, then every line that
+            matches is used to compute a single rate. Its maximum
+            value is reported when the script finishes.
+
+            If there is one () sub-expression, then the text matched
+            by the sub-expression is used to identify a rate lookup
+            key, similar to the lookup key used by the ratelimit
+            ACL condition. For example, you might write a regex
+            to match the client IP address, or the authenticated
+            username. Separate rates are computed for each different
+            client and the maximum rate for each client is reported
+            when the script finishes.
+
+            If there are two () sub-expressions, then the text matched
+            by the first sub-expression is used to identify a rate
+            lookup key as above, and the second is used to match the
+            message size recorded in the log line, e.g. "S=(\\d+)".
+            In this case the byte rate is computed instead of the
+            message rate, similar to the per_byte option of the
+            ratelimit ACL condition.
+
+<logfile>   The log files to be processed can be specified on the
+            command line after the other arguments; if no filenames
+            are specified the script will read from stdin.
+
+examples:
+
+./ratelimit.pl 1 ' <= .*? \[(.*?)\]' <logfile>
+
+            Compute burst sending rate like ACL condition
+            ratelimit = 0 / 1s / strict / \$sender_host_address
+
+./ratelimit.pl 3600 '<= (.*?) ' <logfile>
+
+            Compute sending rate like ACL condition
+            ratelimit = 0 / 1h / strict / \$sender_address
+
 END
   exit 1;
 }
@@ -87,7 +109,7 @@ my %max;
 
 sub debug ($) {
   my $key = shift;
-  printf "%s\t%12d %8s %5.2f %5.2f\n",
+  printf STDERR "%s\t%12d %8s %5.2f %5.2f\n",
     $_, $time{$key}, $key, $max{$key}, $rate{$key};
 }
 
@@ -104,7 +126,7 @@ while (<>) {
     my $prog_now = substr $_, 0, 14;
     if ($progtime ne $prog_now) {
       $progtime = $prog_now;
-      print "$progtime\n";
+      print STDERR "$progtime\n";
     }
   }
   if (not defined $time{$key}) {
index c24bb89..5708871 100644 (file)
@@ -9,3 +9,4 @@ eximdir/
 Makefile
 spool/
 test-*
+failed-summary.log
index 3c12f36..fda4d5f 100644 (file)
@@ -49,12 +49,12 @@ bin/client:     src/client.c Makefile
                @echo " "
 
 bin/client-gnutls: src/client.c Makefile
-               $(CC) $(CFLAGS) -DHAVE_GNUTLS $(LDFLAGS) -lgnutls -lgcrypt -o bin/client-gnutls src/client.c
+               $(CC) $(CFLAGS) -DHAVE_GNUTLS $(LDFLAGS) -o bin/client-gnutls src/client.c -lgnutls -lgcrypt
                @echo ">>> bin/client-gnutls command built"
                @echo " "
 
 bin/client-ssl: src/client.c Makefile
-               $(CC) $(CFLAGS) -DHAVE_OPENSSL $(LDFLAGS) -lssl -lcrypto -o bin/client-ssl src/client.c
+               $(CC) $(CFLAGS) -DHAVE_OPENSSL $(LDFLAGS) -o bin/client-ssl src/client.c -lssl -lcrypto
                @echo ">>> bin/client-ssl command built"
                @echo " "
 
diff --git a/test/confs/5700 b/test/confs/5700
new file mode 100644 (file)
index 0000000..52b2801
--- /dev/null
@@ -0,0 +1,67 @@
+# Exim test configuration 5700
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+rfc1413_query_timeout = 0s
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+# ----- Main settings -----
+
+acl_smtp_rcpt = accept
+acl_smtp_data = accept
+
+
+# ----- ACL -----
+
+begin acl
+
+logger:
+    accept condition = ${if eq {$acl_arg2}{domain1}}
+          logwrite = \
+           $acl_arg1 \
+           ip <$tpda_delivery_ip> \
+           port <$tpda_delivery_port> \
+           fqdn <$tpda_delivery_fqdn> \
+           local_part <$tpda_delivery_local_part> \
+           domain <$tpda_delivery_domain> \
+           confirmation <$tpda_delivery_confirmation> \
+           errno <$tpda_defer_errno> \
+           errstr <$tpda_defer_errstr> \
+           router <$router_name> \
+           transport <$transport_name>
+
+    accept logwrite = $this_expansion_will_fail
+
+# ----- Routers -----
+
+begin routers
+
+dump_bounces:
+  driver = redirect
+  senders = :
+  data = :blackhole:
+
+others:
+  driver = manualroute
+  route_list = * 127.0.0.1 byname
+  self = send
+  transport = smtp
+  no_more
+
+
+# ----- Transports -----
+
+begin transports
+
+smtp:
+  driver = smtp
+  port = PORT_S
+  command_timeout = 1s
+  final_timeout = 1s
+  tpda_delivery_action =   ${acl {logger} {delivery} {$domain} }
+  tpda_host_defer_action = ${acl {logger} {deferral} {$domain} }
+
+# End
diff --git a/test/log/5700 b/test/log/5700
new file mode 100644 (file)
index 0000000..d119365
--- /dev/null
@@ -0,0 +1,22 @@
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qqf
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userx@domain1 R=others T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmaY-0005vi-00 delivery ip <127.0.0.1> port <1224> fqdn <127.0.0.1> local_part <userx> domain <domain1> confirmation <250 OK> errno <0> errstr <> router <others> transport <smtp>
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qqf
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
+1999-03-02 09:44:33 Start queue run: pid=pppp -qqf
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@domain2 R=others T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmaX-0005vi-00 failed to expand tpda_deliver_action in smtp: error from acl "logger"
+
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 End queue run: pid=pppp -qqf
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@the.local.host.name U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaZ-0005vi-00 SMTP timeout while connected to 127.0.0.1 [127.0.0.1] after EHLO the.local.host.name: Connection timed out
+1999-03-02 09:44:33 10HmaZ-0005vi-00 deferral ip <127.0.0.1> port <1224> fqdn <127.0.0.1> local_part <userx> domain <domain1> confirmation <> errno <110> errstr <SMTP timeout while connected to 127.0.0.1 [127.0.0.1] after EHLO the.local.host.name: Connection timed out> router <others> transport <smtp>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == userx@domain1 R=others T=smtp defer (dd): Connection timed out: SMTP timeout while connected to 127.0.0.1 [127.0.0.1] after EHLO the.local.host.name
+1999-03-02 09:44:33 10HmaZ-0005vi-00 ** userx@domain1: retry timeout exceeded
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= <> R=10HmaZ-0005vi-00 U=EXIMUSER P=local S=sss
+1999-03-02 09:44:33 10HmbA-0005vi-00 => :blackhole: <CALLER@the.local.host.name> R=dump_bounces
+1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
diff --git a/test/paniclog/5700 b/test/paniclog/5700
new file mode 100644 (file)
index 0000000..4f28d19
--- /dev/null
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 failed to expand tpda_deliver_action in smtp: error from acl "logger"
+
diff --git a/test/scripts/5700-tpt-post-dlv-action/5700 b/test/scripts/5700-tpt-post-dlv-action/5700
new file mode 100644 (file)
index 0000000..b85231b
--- /dev/null
@@ -0,0 +1,64 @@
+# Arbtirary expansion after transport
+# (EXPERIMENTAL_TPDA)
+#
+need_ipv4
+#
+exim -odq userx@domain1
+A deliverable message
+****
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250 HELP
+MAIL
+250 OK
+RCPT
+250 OK
+DATA
+354 More...
+.
+250 OK
+QUIT
+220 OK
+****
+exim -qqf
+****
+#
+#
+#
+#
+exim -odq userx@domain2
+A deliverable message which will hit a coding error in the config
+****
+server PORT_S
+220 ESMTP
+EHLO
+250-OK
+250 HELP
+MAIL
+250 OK
+RCPT
+250 OK
+DATA
+354 More...
+.
+250 OK
+QUIT
+220 OK
+****
+exim -qqf
+****
+#
+#
+#
+server PORT_S
+220 ESMTP
+EHLO
+*sleep 4
+****
+exim -odi userx@domain1
+A message which will hit a timeout at the destination server
+.
+****
+#
diff --git a/test/scripts/5700-tpt-post-dlv-action/REQUIRES b/test/scripts/5700-tpt-post-dlv-action/REQUIRES
new file mode 100644 (file)
index 0000000..4444658
--- /dev/null
@@ -0,0 +1 @@
+support Experimental_TPDA
diff --git a/test/stderr/5700 b/test/stderr/5700
new file mode 100644 (file)
index 0000000..4f28d19
--- /dev/null
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 failed to expand tpda_deliver_action in smtp: error from acl "logger"
+
diff --git a/test/stdout/5700 b/test/stdout/5700
new file mode 100644 (file)
index 0000000..a45b44c
--- /dev/null
@@ -0,0 +1,60 @@
+
+******** SERVER ********
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO the.local.host.name
+250-OK
+250 HELP
+MAIL FROM:<CALLER@the.local.host.name>
+250 OK
+RCPT TO:<userx@domain1>
+250 OK
+DATA
+354 More...
+Received: from CALLER by the.local.host.name with local (Exim x.yz)
+       (envelope-from <CALLER@the.local.host.name>)
+       id 10HmaY-0005vi-00
+       for userx@domain1; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmaY-0005vi-00@the.local.host.name>
+From: CALLER_NAME <CALLER@the.local.host.name>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+A deliverable message
+.
+250 OK
+QUIT
+220 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO the.local.host.name
+250-OK
+250 HELP
+MAIL FROM:<CALLER@the.local.host.name>
+250 OK
+RCPT TO:<userx@domain2>
+250 OK
+DATA
+354 More...
+Received: from CALLER by the.local.host.name with local (Exim x.yz)
+       (envelope-from <CALLER@the.local.host.name>)
+       id 10HmaX-0005vi-00
+       for userx@domain2; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmaX-0005vi-00@the.local.host.name>
+From: CALLER_NAME <CALLER@the.local.host.name>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+A deliverable message which will hit a coding error in the config
+.
+250 OK
+QUIT
+220 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 ESMTP
+EHLO the.local.host.name
+*sleep 4
+End of script