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 85d4316b29f904b081abb009e265b25683f5b0e1..0f603e4eb0de08e82704429c6c0d8ce18f2837e7 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 2b038e32eecdf95026ec230763c2cc1933995ffe..9c8b9df7b15314f2887b895820d6ff1767929821 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 f9be19cf701841d6434fe84c6337ea3384b1c188..271ab0ba042cc5f0b4899f1a7a60e824863712ad 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 0611b1f9953f54faa90e480b91f28e709cf118ca..ea9076a00e520429cb08ad67bea553f33b7df09f 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 e29c1eb25e11ffe47f1af6750af24998d588e4d5..1db70f7157a1506677337ff4c4e9ac8c563a80ac 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 1594f6858d95978a1deab0fdcb70af000b07dd5f..bf7ac63fb917e91000fd2e4e62a635b26fe22ac8 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 23e63d553d188426538ad0e826a0b72d090812db..bc6a69fbf5e1ca266b0fda6ce821a93c66344d0f 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 8ab0456d83e74d3bf400c957b17bf57d7d862ec6..c5053ba7cecf6317ca4d8fb2c748cd4ff50cc823 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 edef45dba2eee90b82774da9542343c0ccdbd666..a22ee2af4ce004a37be2f2b12ef26ab278bab27b 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 05bb0ae86191e5bf8eb7ba6ab601627e8b935abf..d4589cd18f2faddf3dc85ab8c4960cf120ce0848 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 2cc16881b119416f7e2796a0473208d14910928b..104b5fa7a74b2e6db4299b8e0353339e56370dd2 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 53aa2106b7834d2095160b066416b20bcc94e497..baf9a0f8574287c7979098720c3d57ee9289c5ee 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 7dd1afb85d828f26dad55785feca43fdd661b32b..d2540be620531df975b39f85a4150d2f1cfa408f 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 25cc5490a8273ef394849da4b8435327b4894728..9918f3116fb59673e80663bbe15086979de6da10 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 8e85294bc337d155234c1fd45d9cb7382fa14164..0d88016473ef5f913231446df34f24ba808c72c0 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 749125c4f80f5a3b13d423eaae70bfd9a8ba5394..d7fd43ab1b07d15ab1c96d9bd1eda096347be59f 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 c24bb8993c1d94cdfbbebbced9312eaa9614ce5d..57088717e8078e36ba02c9b36f40b6b4a68e11a9 100644 (file)
@@ -9,3 +9,4 @@ eximdir/
 Makefile
 spool/
 test-*
+failed-summary.log
index 3c12f36253f84e3dfdfdee2339db470ba157826b..fda4d5f64124d5902a2dcc47f11d99dc3df1367a 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