Merge branch 'CHUNKING'
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 6 Aug 2016 13:04:45 +0000 (14:04 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 6 Aug 2016 13:04:45 +0000 (14:04 +0100)
26 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/deliver.c
src/src/dkim.c
src/src/expand.c
src/src/functions.h
src/src/pdkim/pdkim.c
src/src/pdkim/pdkim.h
src/src/receive.c
src/src/string.c
src/src/transport.c
src/src/transports/smtp.c
test/log/0555
test/log/4010
test/scripts/0000-Basic/0002
test/scripts/0000-Basic/0555
test/stderr/0002
test/stderr/0092
test/stderr/0393
test/stderr/0402
test/stderr/0544
test/stderr/4504 [new file with mode: 0644]
test/stderr/5410
test/stderr/5420
test/stdout/0002

index 6302f51..d18dd0c 100644 (file)
@@ -10090,6 +10090,21 @@ Last:user@example.com
 user@example.com
 .endd
 
+.new
+.vitem &*${base32:*&<&'digits'&>&*}*&
+.cindex "&%base32%& expansion item"
+.cindex "expansion" "conversion to base 32"
+The string must consist entirely of decimal digits. The number is converted to
+base 32 and output as a (empty, for zero) string of characters.
+Only lowercase letters are used.
+
+.vitem &*${base32d:*&<&'base-32&~digits'&>&*}*&
+.cindex "&%base32d%& expansion item"
+.cindex "expansion" "conversion to base 32"
+The string must consist entirely of base-32 digits.
+The number is converted to decimal and output as a string.
+.wen
+
 .vitem &*${base62:*&<&'digits'&>&*}*&
 .cindex "&%base62%& expansion item"
 .cindex "expansion" "conversion to base 62"
@@ -19883,12 +19898,17 @@ list1:   :include:/opt/lists/list1
 .endd
 .next
 .cindex "address redirection" "to black hole"
-Sometimes you want to throw away mail to a particular local part. Making the
-&%data%& option expand to an empty string does not work, because that causes
-the router to decline. Instead, the alias item
+.cindex "delivery" "discard"
+.cindex "delivery" "blackhole"
 .cindex "black hole"
 .cindex "abandoning mail"
-&':blackhole:'& can be used. It does what its name implies. No delivery is
+Sometimes you want to throw away mail to a particular local part.  Making the
+&%data%& option expand to an empty string does not work, because that causes
+the router to decline. Instead, the alias item
+.code
+:blackhole:
+.endd
+can be used. It does what its name implies. No delivery is
 done, and no error message is generated. This has the same effect as specifying
 &_/dev/null_& as a destination, but it can be independently disabled.
 
@@ -31555,7 +31575,7 @@ condition defers.
 
 Unix and TCP socket specifications may be mixed in any order.
 Each element of the list is a list itself, space-separated by default
-and changeable in the usual way.
+and changeable in the usual way; take care to not double the separator.
 
 For TCP socket specifications a host name or IP (v4 or v6, but
 subject to list-separator quoting rules) address can be used,
@@ -31682,6 +31702,11 @@ spam bar is 50 characters.
 A multiline text table, containing the full SpamAssassin report for the
 message. Useful for inclusion in headers or reject messages.
 This variable is only usable in a DATA-time ACL.
+.new
+Beware that SpamAssassin may return non-ASCII characters, especially
+when running in country-specific locales, which are not legal
+unencoded in headers.
+.wen
 
 .vitem &$spam_action$&
 For SpamAssassin either 'reject' or 'no action' depending on the
@@ -35419,6 +35444,7 @@ picked out by the distinctive two-character flags that immediately follow the
 timestamp. The flags are:
 .display
 &`<=`&     message arrival
+&`(=`&     message fakereject
 &`=>`&     normal message delivery
 &`->`&     additional address in same delivery
 &`>>`&     cutthrough message delivery
@@ -38091,7 +38117,7 @@ senders).
 .section "Signing outgoing messages" "SECDKIMSIGN"
 .cindex "DKIM" "signing"
 
-Signing is implemented by setting private options on the SMTP transport.
+Signing is enabled by setting private options on the SMTP transport.
 These options take (expandable) strings as arguments.
 
 .option dkim_domain smtp string&!! unset
index 0fe63f1..11b25f8 100644 (file)
@@ -55,6 +55,19 @@ JH/13 Cutthrough: expand transport dkim_domain option when testing for dkim
       empty is permissible (obviously it should depend only on data available
       when the cutthrough connection is made).
 
+JH/14 Fix logging of errors under PIPELINING.  Previously the log line giving
+      the relevant preceding SMTP command did not note the pipelining mode.
+
+JH/15 Fix counting of empty lines in $body_linecount and $message_linecount.
+      Previously they were not counted.
+
+JH/16 DANE: treat a TLSA lookup response having all non-TLSA RRs, the same
+      as one having no matching records.  Previously we deferred the message
+      that needed the lookup.
+
+JH/17 Fakereject: previously logged as a norml message arrival "<="; now
+      distinguished as "(=".
+
 
 Exim version 4.87
 -----------------
index 9e2be83..719bedf 100644 (file)
@@ -26,7 +26,9 @@ Version 4.88
     the queue to be used for a message.  A $queue_name variable gives
     visibility.
 
- 6. The CHUNKING ESMTP extension from RFC 3030.  May give some slight
+ 6. New expansion operators base32/base32d.
+
+ 7. The CHUNKING ESMTP extension from RFC 3030.  May give some slight
     performance increase and network load decrease.  Main config option
     chunking_advertise_hosts, and smtp transport option hosts_try_chunking
     for control.
index a8d740c..eae6757 100644 (file)
@@ -836,6 +836,184 @@ router_name = transport_name = NULL;
 
 
 
+/******************************************************************************/
+
+
+/*************************************************
+*        Generate local prt for logging          *
+*************************************************/
+
+/* This function is a subroutine for use in string_log_address() below.
+
+Arguments:
+  addr        the address being logged
+  yield       the current dynamic buffer pointer
+  sizeptr     points to current size
+  ptrptr      points to current insert pointer
+
+Returns:      the new value of the buffer pointer
+*/
+
+static uschar *
+string_get_localpart(address_item *addr, uschar *yield, int *sizeptr,
+  int *ptrptr)
+{
+uschar * s;
+
+s = addr->prefix;
+if (testflag(addr, af_include_affixes) && s)
+  {
+#ifdef SUPPORT_I18N
+  if (testflag(addr, af_utf8_downcvt))
+    s = string_localpart_utf8_to_alabel(s, NULL);
+#endif
+  yield = string_cat(yield, sizeptr, ptrptr, s);
+  }
+
+s = addr->local_part;
+#ifdef SUPPORT_I18N
+if (testflag(addr, af_utf8_downcvt))
+  s = string_localpart_utf8_to_alabel(s, NULL);
+#endif
+yield = string_cat(yield, sizeptr, ptrptr, s);
+
+s = addr->suffix;
+if (testflag(addr, af_include_affixes) && s)
+  {
+#ifdef SUPPORT_I18N
+  if (testflag(addr, af_utf8_downcvt))
+    s = string_localpart_utf8_to_alabel(s, NULL);
+#endif
+  yield = string_cat(yield, sizeptr, ptrptr, s);
+  }
+
+return yield;
+}
+
+
+/*************************************************
+*          Generate log address list             *
+*************************************************/
+
+/* This function generates a list consisting of an address and its parents, for
+use in logging lines. For saved onetime aliased addresses, the onetime parent
+field is used. If the address was delivered by a transport with rcpt_include_
+affixes set, the af_include_affixes bit will be set in the address. In that
+case, we include the affixes here too.
+
+Arguments:
+  str           points to start of growing string, or NULL
+  size          points to current allocation for string
+  ptr           points to offset for append point; updated on exit
+  addr          bottom (ultimate) address
+  all_parents   if TRUE, include all parents
+  success       TRUE for successful delivery
+
+Returns:        a growable string in dynamic store
+*/
+
+static uschar *
+string_log_address(uschar * str, int * size, int * ptr,
+  address_item *addr, BOOL all_parents, BOOL success)
+{
+BOOL add_topaddr = TRUE;
+address_item *topaddr;
+
+/* Find the ultimate parent */
+
+for (topaddr = addr; topaddr->parent; topaddr = topaddr->parent) ;
+
+/* We start with just the local part for pipe, file, and reply deliveries, and
+for successful local deliveries from routers that have the log_as_local flag
+set. File deliveries from filters can be specified as non-absolute paths in
+cases where the transport is goin to complete the path. If there is an error
+before this happens (expansion failure) the local part will not be updated, and
+so won't necessarily look like a path. Add extra text for this case. */
+
+if (  testflag(addr, af_pfr)
+   || (  success
+      && addr->router && addr->router->log_as_local
+      && addr->transport && addr->transport->info->local
+   )  )
+  {
+  if (testflag(addr, af_file) && addr->local_part[0] != '/')
+    str = string_catn(str, size, ptr, CUS"save ", 5);
+  str = string_get_localpart(addr, str, size, ptr);
+  }
+
+/* Other deliveries start with the full address. It we have split it into local
+part and domain, use those fields. Some early failures can happen before the
+splitting is done; in those cases use the original field. */
+
+else
+  {
+  uschar * cmp = str + *ptr;
+
+  if (addr->local_part)
+    {
+    const uschar * s;
+    str = string_get_localpart(addr, str, size, ptr);
+    str = string_catn(str, size, ptr, US"@", 1);
+    s = addr->domain;
+#ifdef SUPPORT_I18N
+    if (testflag(addr, af_utf8_downcvt))
+      s = string_localpart_utf8_to_alabel(s, NULL);
+#endif
+    str = string_cat(str, size, ptr, s);
+    }
+  else
+    str = string_cat(str, size, ptr, addr->address);
+
+  /* If the address we are going to print is the same as the top address,
+  and all parents are not being included, don't add on the top address. First
+  of all, do a caseless comparison; if this succeeds, do a caseful comparison
+  on the local parts. */
+
+  str[*ptr] = 0;
+  if (  strcmpic(cmp, topaddr->address) == 0
+     && Ustrncmp(cmp, topaddr->address, Ustrchr(cmp, '@') - cmp) == 0
+     && !addr->onetime_parent
+     && (!all_parents || !addr->parent || addr->parent == topaddr)
+     )
+    add_topaddr = FALSE;
+  }
+
+/* If all parents are requested, or this is a local pipe/file/reply, and
+there is at least one intermediate parent, show it in brackets, and continue
+with all of them if all are wanted. */
+
+if (  (all_parents || testflag(addr, af_pfr))
+   && addr->parent
+   && addr->parent != topaddr)
+  {
+  uschar *s = US" (";
+  address_item *addr2;
+  for (addr2 = addr->parent; addr2 != topaddr; addr2 = addr2->parent)
+    {
+    str = string_catn(str, size, ptr, s, 2);
+    str = string_cat (str, size, ptr, addr2->address);
+    if (!all_parents) break;
+    s = US", ";
+    }
+  str = string_catn(str, size, ptr, US")", 1);
+  }
+
+/* Add the top address if it is required */
+
+if (add_topaddr)
+  str = string_append(str, size, ptr, 3,
+    US" <",
+    addr->onetime_parent ? addr->onetime_parent : topaddr->address,
+    US">");
+
+return str;
+}
+
+
+/******************************************************************************/
+
+
+
 /* If msg is NULL this is a delivery log and logchar is used. Otherwise
 this is a nonstandard call; no two-character delivery flag is written
 but sender-host and sender are prefixed and "msg" is inserted in the log line.
@@ -846,11 +1024,10 @@ Arguments:
 void
 delivery_log(int flags, address_item * addr, int logchar, uschar * msg)
 {
-uschar *log_address;
 int size = 256;         /* Used for a temporary, */
 int ptr = 0;            /* expanding buffer, for */
-uschar *s;              /* building log lines;   */
-void *reset_point;      /* released afterwards.  */
+uschar * s;             /* building log lines;   */
+void * reset_point;     /* released afterwards.  */
 
 /* Log the delivery on the main log. We use an extensible string to build up
 the log line, and reset the store afterwards. Remote deliveries should always
@@ -864,14 +1041,14 @@ pointer to a single host item in their host list, for use by the transport. */
 
 s = reset_point = store_get(size);
 
-log_address = string_log_address(addr, LOGGING(all_parents), TRUE);
 if (msg)
-  s = string_append(s, &size, &ptr, 3, host_and_ident(TRUE), US" ", log_address);
+  s = string_append(s, &size, &ptr, 2, host_and_ident(TRUE), US" ");
 else
   {
   s[ptr++] = logchar;
-  s = string_append(s, &size, &ptr, 2, US"> ", log_address);
+  s = string_catn(s, &size, &ptr, US"> ", 2);
   }
+s = string_log_address(s, &size, &ptr, addr, LOGGING(all_parents), TRUE);
 
 if (LOGGING(sender_on_delivery) || msg)
   s = string_append(s, &size, &ptr, 3, US" F=<",
@@ -1017,6 +1194,163 @@ return;
 
 
 
+static void
+deferral_log(address_item * addr, uschar * now,
+  int logflags, uschar * driver_name, uschar * driver_kind)
+{
+int size = 256;         /* Used for a temporary, */
+int ptr = 0;            /* expanding buffer, for */
+uschar * s;             /* building log lines;   */
+void * reset_point;     /* released afterwards.  */
+
+uschar ss[32];
+
+/* Build up the line that is used for both the message log and the main
+log. */
+
+s = reset_point = store_get(size);
+
+/* Create the address string for logging. Must not do this earlier, because
+an OK result may be changed to FAIL when a pipe returns text. */
+
+s = string_log_address(s, &size, &ptr, addr, LOGGING(all_parents), FALSE);
+
+if (*queue_name)
+  s = string_append(s, &size, &ptr, 2, US" Q=", queue_name);
+
+/* Either driver_name contains something and driver_kind contains
+" router" or " transport" (note the leading space), or driver_name is
+a null string and driver_kind contains "routing" without the leading
+space, if all routing has been deferred. When a domain has been held,
+so nothing has been done at all, both variables contain null strings. */
+
+if (driver_name)
+  {
+  if (driver_kind[1] == 't' && addr->router)
+    s = string_append(s, &size, &ptr, 2, US" R=", addr->router->name);
+  Ustrcpy(ss, " ?=");
+  ss[1] = toupper(driver_kind[1]);
+  s = string_append(s, &size, &ptr, 2, ss, driver_name);
+  }
+else if (driver_kind)
+  s = string_append(s, &size, &ptr, 2, US" ", driver_kind);
+
+/*XXX need an s+s+p sprintf */
+sprintf(CS ss, " defer (%d)", addr->basic_errno);
+s = string_cat(s, &size, &ptr, ss);
+
+if (addr->basic_errno > 0)
+  s = string_append(s, &size, &ptr, 2, US": ",
+    US strerror(addr->basic_errno));
+
+if (addr->host_used)
+  {
+  s = string_append(s, &size, &ptr, 5,
+                   US" H=", addr->host_used->name,
+                   US" [",  addr->host_used->address, US"]");
+  if (LOGGING(outgoing_port))
+    {
+    int port = addr->host_used->port;
+    s = string_append(s, &size, &ptr, 2,
+         US":", port == PORT_NONE ? US"25" : string_sprintf("%d", port));
+    }
+  }
+
+if (addr->message)
+  s = string_append(s, &size, &ptr, 2, US": ", addr->message);
+
+s[ptr] = 0;
+
+/* Log the deferment in the message log, but don't clutter it
+up with retry-time defers after the first delivery attempt. */
+
+if (deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE)
+  deliver_msglog("%s %s\n", now, s);
+
+/* Write the main log and reset the store.
+For errors of the type "retry time not reached" (also remotes skipped
+on queue run), logging is controlled by L_retry_defer. Note that this kind
+of error number is negative, and all the retry ones are less than any
+others. */
+
+
+log_write(addr->basic_errno <= ERRNO_RETRY_BASE ? L_retry_defer : 0, logflags,
+  "== %s", s);
+
+store_reset(reset_point);
+return;
+}
+
+
+
+static void
+failure_log(address_item * addr, uschar * driver_kind, uschar * now)
+{
+int size = 256;         /* Used for a temporary, */
+int ptr = 0;            /* expanding buffer, for */
+uschar * s;             /* building log lines;   */
+void * reset_point;     /* released afterwards.  */
+
+/* Build up the log line for the message and main logs */
+
+s = reset_point = store_get(size);
+
+/* Create the address string for logging. Must not do this earlier, because
+an OK result may be changed to FAIL when a pipe returns text. */
+
+s = string_log_address(s, &size, &ptr, addr, LOGGING(all_parents), FALSE);
+
+if (LOGGING(sender_on_delivery))
+  s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">");
+
+if (*queue_name)
+  s = string_append(s, &size, &ptr, 2, US" Q=", queue_name);
+
+/* Return path may not be set if no delivery actually happened */
+
+if (used_return_path && LOGGING(return_path_on_delivery))
+  s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">");
+
+if (addr->router)
+  s = string_append(s, &size, &ptr, 2, US" R=", addr->router->name);
+if (addr->transport)
+  s = string_append(s, &size, &ptr, 2, US" T=", addr->transport->name);
+
+if (addr->host_used)
+  s = d_hostlog(s, &size, &ptr, addr);
+
+#ifdef SUPPORT_TLS
+s = d_tlslog(s, &size, &ptr, addr);
+#endif
+
+if (addr->basic_errno > 0)
+  s = string_append(s, &size, &ptr, 2, US": ", US strerror(addr->basic_errno));
+
+if (addr->message)
+  s = string_append(s, &size, &ptr, 2, US": ", addr->message);
+
+s[ptr] = 0;
+
+/* Do the logging. For the message log, "routing failed" for those cases,
+just to make it clearer. */
+
+if (driver_kind)
+  deliver_msglog("%s %s failed for %s\n", now, driver_kind, s);
+else
+  deliver_msglog("%s %s\n", now, s);
+
+log_write(0, LOG_MAIN, "** %s", s);
+
+#ifndef DISABLE_EVENT
+msg_event_raise(US"msg:fail:delivery", addr);
+#endif
+
+store_reset(reset_point);
+return;
+}
+
+
+
 /*************************************************
 *    Actions at the end of handling an address   *
 *************************************************/
@@ -1042,12 +1376,6 @@ post_process_one(address_item *addr, int result, int logflags, int driver_type,
 uschar *now = tod_stamp(tod_log);
 uschar *driver_kind = NULL;
 uschar *driver_name = NULL;
-uschar *log_address;
-
-int size = 256;         /* Used for a temporary, */
-int ptr = 0;            /* expanding buffer, for */
-uschar *s;              /* building log lines;   */
-void *reset_point;      /* released afterwards.  */
 
 DEBUG(D_deliver) debug_printf("post-process %s (%d)\n", addr->address, result);
 
@@ -1253,85 +1581,7 @@ else if (result == DEFER || result == PANIC)
   log or the main log for SMTP defers. */
 
   if (!queue_2stage || addr->basic_errno != 0)
-    {
-    uschar ss[32];
-
-    /* For errors of the type "retry time not reached" (also remotes skipped
-    on queue run), logging is controlled by L_retry_defer. Note that this kind
-    of error number is negative, and all the retry ones are less than any
-    others. */
-
-    unsigned int use_log_selector = addr->basic_errno <= ERRNO_RETRY_BASE
-      ? L_retry_defer : 0;
-
-    /* Build up the line that is used for both the message log and the main
-    log. */
-
-    s = reset_point = store_get(size);
-
-    /* Create the address string for logging. Must not do this earlier, because
-    an OK result may be changed to FAIL when a pipe returns text. */
-
-    log_address = string_log_address(addr, LOGGING(all_parents), result == OK);
-
-    s = string_cat(s, &size, &ptr, log_address);
-
-    if (*queue_name)
-      s = string_append(s, &size, &ptr, 2, US" Q=", queue_name);
-
-    /* Either driver_name contains something and driver_kind contains
-    " router" or " transport" (note the leading space), or driver_name is
-    a null string and driver_kind contains "routing" without the leading
-    space, if all routing has been deferred. When a domain has been held,
-    so nothing has been done at all, both variables contain null strings. */
-
-    if (driver_name)
-      {
-      if (driver_kind[1] == 't' && addr->router)
-        s = string_append(s, &size, &ptr, 2, US" R=", addr->router->name);
-      Ustrcpy(ss, " ?=");
-      ss[1] = toupper(driver_kind[1]);
-      s = string_append(s, &size, &ptr, 2, ss, driver_name);
-      }
-    else if (driver_kind)
-      s = string_append(s, &size, &ptr, 2, US" ", driver_kind);
-
-    sprintf(CS ss, " defer (%d)", addr->basic_errno);
-    s = string_cat(s, &size, &ptr, ss);
-
-    if (addr->basic_errno > 0)
-      s = string_append(s, &size, &ptr, 2, US": ",
-        US strerror(addr->basic_errno));
-
-    if (addr->host_used)
-      {
-      s = string_append(s, &size, &ptr, 5,
-                       US" H=", addr->host_used->name,
-                       US" [",  addr->host_used->address, US"]");
-      if (LOGGING(outgoing_port))
-       {
-       int port = addr->host_used->port;
-       s = string_append(s, &size, &ptr, 2,
-             US":", port == PORT_NONE ? US"25" : string_sprintf("%d", port));
-       }
-      }
-
-    if (addr->message)
-      s = string_append(s, &size, &ptr, 2, US": ", addr->message);
-
-    s[ptr] = 0;
-
-    /* Log the deferment in the message log, but don't clutter it
-    up with retry-time defers after the first delivery attempt. */
-
-    if (deliver_firsttime || addr->basic_errno > ERRNO_RETRY_BASE)
-      deliver_msglog("%s %s\n", now, s);
-
-    /* Write the main log and reset the store */
-
-    log_write(use_log_selector, logflags, "== %s", s);
-    store_reset(reset_point);
-    }
+    deferral_log(addr, now, logflags, driver_name, driver_kind);
   }
 
 
@@ -1386,64 +1636,7 @@ else
     addr_failed = addr;
     }
 
-  /* Build up the log line for the message and main logs */
-
-  s = reset_point = store_get(size);
-
-  /* Create the address string for logging. Must not do this earlier, because
-  an OK result may be changed to FAIL when a pipe returns text. */
-
-  log_address = string_log_address(addr, LOGGING(all_parents), result == OK);
-
-  s = string_cat(s, &size, &ptr, log_address);
-
-  if (LOGGING(sender_on_delivery))
-    s = string_append(s, &size, &ptr, 3, US" F=<", sender_address, US">");
-
-  if (*queue_name)
-    s = string_append(s, &size, &ptr, 2, US" Q=", queue_name);
-
-  /* Return path may not be set if no delivery actually happened */
-
-  if (used_return_path && LOGGING(return_path_on_delivery))
-    s = string_append(s, &size, &ptr, 3, US" P=<", used_return_path, US">");
-
-  if (addr->router)
-    s = string_append(s, &size, &ptr, 2, US" R=", addr->router->name);
-  if (addr->transport)
-    s = string_append(s, &size, &ptr, 2, US" T=", addr->transport->name);
-
-  if (addr->host_used)
-    s = d_hostlog(s, &size, &ptr, addr);
-
-#ifdef SUPPORT_TLS
-  s = d_tlslog(s, &size, &ptr, addr);
-#endif
-
-  if (addr->basic_errno > 0)
-    s = string_append(s, &size, &ptr, 2, US": ",
-      US strerror(addr->basic_errno));
-
-  if (addr->message)
-    s = string_append(s, &size, &ptr, 2, US": ", addr->message);
-
-  s[ptr] = 0;
-
-  /* Do the logging. For the message log, "routing failed" for those cases,
-  just to make it clearer. */
-
-  if (driver_name)
-    deliver_msglog("%s %s\n", now, s);
-  else
-    deliver_msglog("%s %s failed for %s\n", now, driver_kind, s);
-
-  log_write(0, LOG_MAIN, "** %s", s);
-
-#ifndef DISABLE_EVENT
-  msg_event_raise(US"msg:fail:delivery", addr);
-#endif
-
-  store_reset(reset_point);
+  failure_log(addr, driver_name ? NULL : driver_kind, now);
   }
 
 /* Ensure logging is turned on again in all cases */
index a09ec7e..f09d438 100644 (file)
@@ -28,7 +28,7 @@ dns_record *rr;
 
 lookup_dnssec_authenticated = NULL;
 if (dns_lookup(&dnsa, US name, T_TXT, NULL) != DNS_SUCCEED)
-  return PDKIM_FAIL;
+  return PDKIM_FAIL;   /*XXX better error detail?  logging? */
 
 /* Search for TXT record */
 
@@ -51,12 +51,12 @@ for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
       rr_offset += len;
       answer_offset += len;
       if (answer_offset >= PDKIM_DNS_TXT_MAX_RECLEN)
-       return PDKIM_FAIL;
+       return PDKIM_FAIL;      /*XXX better error detail?  logging? */
       }
     return PDKIM_OK;
     }
 
-return PDKIM_FAIL;
+return PDKIM_FAIL;     /*XXX better error detail?  logging? */
 }
 
 
@@ -98,10 +98,16 @@ store_pool = dkim_verify_oldpool;
 void
 dkim_exim_verify_feed(uschar * data, int len)
 {
+int rc;
+
 store_pool = POOL_PERM;
 if (  dkim_collect_input
-   && pdkim_feed(dkim_verify_ctx, (char *)data, len) != PDKIM_OK)
+   && (rc = pdkim_feed(dkim_verify_ctx, (char *)data, len)) != PDKIM_OK)
+  {
+  log_write(0, LOG_MAIN,
+            "DKIM: validation error: %.100s", pdkim_errstr(rc));
   dkim_collect_input = FALSE;
+  }
 store_pool = dkim_verify_oldpool;
 }
 
@@ -113,6 +119,7 @@ pdkim_signature *sig = NULL;
 int dkim_signers_size = 0;
 int dkim_signers_ptr = 0;
 dkim_signers = NULL;
+int rc;
 
 store_pool = POOL_PERM;
 
@@ -137,8 +144,12 @@ dkim_collect_input = FALSE;
 
 /* Finish DKIM operation and fetch link to signatures chain */
 
-if (pdkim_feed_finish(dkim_verify_ctx, &dkim_signatures) != PDKIM_OK)
+if ((rc = pdkim_feed_finish(dkim_verify_ctx, &dkim_signatures)) != PDKIM_OK)
+  {
+  log_write(0, LOG_MAIN,
+            "DKIM: validation error: %.100s", pdkim_errstr(rc));
   goto out;
+  }
 
 for (sig = dkim_signatures; sig; sig = sig->next)
   {
@@ -481,8 +492,7 @@ if (!(dkim_domain = expand_cstring(dkim_domain)))
   /* expansion error, do not send message. */
   log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
             "dkim_domain: %s", expand_string_message);
-  rc = NULL;
-  goto CLEANUP;
+  goto bad;
   }
 
 /* Set $dkim_domain expansion variable to each unique domain in list. */
@@ -519,8 +529,7 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
     {
     log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
               "dkim_selector: %s", expand_string_message);
-    rc = NULL;
-    goto CLEANUP;
+    goto bad;
     }
 
   /* Get canonicalization to use */
@@ -531,8 +540,7 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
     /* expansion error, do not send message. */
     log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
               "dkim_canon: %s", expand_string_message);
-    rc = NULL;
-    goto CLEANUP;
+    goto bad;
     }
 
   if (Ustrcmp(dkim_canon_expanded, "relaxed") == 0)
@@ -553,8 +561,7 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
       {
       log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
                 "dkim_sign_headers: %s", expand_string_message);
-      rc = NULL;
-      goto CLEANUP;
+      goto bad;
       }
                        /* else pass NULL, which means default header list */
 
@@ -564,8 +571,7 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
     {
     log_write(0, LOG_MAIN | LOG_PANIC, "failed to expand "
               "dkim_private_key: %s", expand_string_message);
-    rc = NULL;
-    goto CLEANUP;
+    goto bad;
     }
 
   if (  Ustrlen(dkim_private_key_expanded) == 0
@@ -587,25 +593,23 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
       log_write(0, LOG_MAIN | LOG_PANIC, "unable to open "
                 "private key file for reading: %s",
                 dkim_private_key_expanded);
-      rc = NULL;
-      goto CLEANUP;
+      goto bad;
       }
 
     if (read(privkey_fd, big_buffer, big_buffer_size - 2) < 0)
       {
       log_write(0, LOG_MAIN|LOG_PANIC, "unable to read private key file: %s",
                 dkim_private_key_expanded);
-      rc = NULL;
-      goto CLEANUP;
+      goto bad;
       }
 
     (void) close(privkey_fd);
     dkim_private_key_expanded = big_buffer;
     }
 
-  ctx = pdkim_init_sign( (char *) dkim_signing_domain,
-                        (char *) dkim_signing_selector,
-                        (char *) dkim_private_key_expanded,
+  ctx = pdkim_init_sign( CS dkim_signing_domain,
+                        CS dkim_signing_selector,
+                        CS dkim_private_key_expanded,
                         PDKIM_ALGO_RSA_SHA256);
   pdkim_set_optional(ctx,
                      (char *) dkim_sign_headers_expanded,
@@ -616,27 +620,19 @@ while ((dkim_signing_domain = string_nextinlist(&dkim_domain, &sep,
   lseek(dkim_fd, 0, SEEK_SET);
 
   while ((sread = read(dkim_fd, &buf, 4096)) > 0)
-    if (pdkim_feed(ctx, buf, sread) != PDKIM_OK)
-      {
-      rc = NULL;
-      goto CLEANUP;
-      }
+    if ((pdkim_rc = pdkim_feed(ctx, buf, sread)) != PDKIM_OK)
+      goto pk_bad;
 
   /* Handle failed read above. */
   if (sread == -1)
     {
     debug_printf("DKIM: Error reading -K file.\n");
     save_errno = errno;
-    rc = NULL;
-    goto CLEANUP;
+    goto bad;
     }
 
   if ((pdkim_rc = pdkim_feed_finish(ctx, &signature)) != PDKIM_OK)
-    {
-    log_write(0, LOG_MAIN|LOG_PANIC, "DKIM: signing failed (RC %d)", pdkim_rc);
-    rc = NULL;
-    goto CLEANUP;
-    }
+    goto pk_bad;
 
   sigbuf = string_append(sigbuf, &sigsize, &sigptr, 2,
                          US signature->signature_header, US"\r\n");
@@ -654,11 +650,18 @@ else
   rc = US"";
 
 CLEANUP:
-if (ctx)
-  pdkim_free_ctx(ctx);
-store_pool = old_pool;
-errno = save_errno;
-return rc;
+  if (ctx)
+    pdkim_free_ctx(ctx);
+  store_pool = old_pool;
+  errno = save_errno;
+  return rc;
+
+pk_bad:
+  log_write(0, LOG_MAIN|LOG_PANIC,
+               "DKIM: signing failed: %.100s", pdkim_errstr(pdkim_rc));
+bad:
+  rc = NULL;
+  goto CLEANUP;
 }
 
 #endif
index a0b36f7..0fba962 100644 (file)
@@ -199,6 +199,8 @@ enum {
 static uschar *op_table_main[] = {
   US"address",
   US"addresses",
+  US"base32",
+  US"base32d",
   US"base62",
   US"base62d",
   US"base64",
@@ -242,6 +244,8 @@ static uschar *op_table_main[] = {
 enum {
   EOP_ADDRESS =  nelem(op_table_underscore),
   EOP_ADDRESSES,
+  EOP_BASE32,
+  EOP_BASE32D,
   EOP_BASE62,
   EOP_BASE62D,
   EOP_BASE64,
@@ -838,6 +842,9 @@ static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
     }
 
 
+
+static uschar * base32_chars = US"abcdefghijklmnopqrstuvwxyz234567";
+
 /*************************************************
 *           Binary chop search on a table        *
 *************************************************/
@@ -4105,8 +4112,9 @@ while (*s != 0)
       if (next_s == NULL) goto EXPAND_FAILED;  /* message already set */
 
       DEBUG(D_expand)
-        debug_printf("condition: %.*s\n   result: %s\n", (int)(next_s - s), s,
-          cond? "true" : "false");
+        debug_printf("  condition: %.*s\n     result: %s\n",
+         (int)(next_s - s), s,
+          cond ? "true" : "false");
 
       s = next_s;
 
@@ -5166,79 +5174,81 @@ while (*s != 0)
         case 3: goto EXPAND_FAILED;
         }
 
-      if (Ustrcmp(sub[0], "md5") == 0)
-        {
-        type = HMAC_MD5;
-        use_base = &md5_base;
-        hashlen = 16;
-        hashblocklen = 64;
-        }
-      else if (Ustrcmp(sub[0], "sha1") == 0)
-        {
-        type = HMAC_SHA1;
-        use_base = &sha1_ctx;
-        hashlen = 20;
-        hashblocklen = 64;
-        }
-      else
-        {
-        expand_string_message =
-          string_sprintf("hmac algorithm \"%s\" is not recognised", sub[0]);
-        goto EXPAND_FAILED;
-        }
+      if (!skipping)
+       {
+       if (Ustrcmp(sub[0], "md5") == 0)
+         {
+         type = HMAC_MD5;
+         use_base = &md5_base;
+         hashlen = 16;
+         hashblocklen = 64;
+         }
+       else if (Ustrcmp(sub[0], "sha1") == 0)
+         {
+         type = HMAC_SHA1;
+         use_base = &sha1_ctx;
+         hashlen = 20;
+         hashblocklen = 64;
+         }
+       else
+         {
+         expand_string_message =
+           string_sprintf("hmac algorithm \"%s\" is not recognised", sub[0]);
+         goto EXPAND_FAILED;
+         }
 
-      keyptr = sub[1];
-      keylen = Ustrlen(keyptr);
+       keyptr = sub[1];
+       keylen = Ustrlen(keyptr);
 
-      /* If the key is longer than the hash block length, then hash the key
-      first */
+       /* If the key is longer than the hash block length, then hash the key
+       first */
 
-      if (keylen > hashblocklen)
-        {
-        chash_start(type, use_base);
-        chash_end(type, use_base, keyptr, keylen, keyhash);
-        keyptr = keyhash;
-        keylen = hashlen;
-        }
+       if (keylen > hashblocklen)
+         {
+         chash_start(type, use_base);
+         chash_end(type, use_base, keyptr, keylen, keyhash);
+         keyptr = keyhash;
+         keylen = hashlen;
+         }
 
-      /* Now make the inner and outer key values */
+       /* Now make the inner and outer key values */
 
-      memset(innerkey, 0x36, hashblocklen);
-      memset(outerkey, 0x5c, hashblocklen);
+       memset(innerkey, 0x36, hashblocklen);
+       memset(outerkey, 0x5c, hashblocklen);
 
-      for (i = 0; i < keylen; i++)
-        {
-        innerkey[i] ^= keyptr[i];
-        outerkey[i] ^= keyptr[i];
-        }
+       for (i = 0; i < keylen; i++)
+         {
+         innerkey[i] ^= keyptr[i];
+         outerkey[i] ^= keyptr[i];
+         }
 
-      /* Now do the hashes */
+       /* Now do the hashes */
 
-      chash_start(type, use_base);
-      chash_mid(type, use_base, innerkey);
-      chash_end(type, use_base, sub[2], Ustrlen(sub[2]), innerhash);
+       chash_start(type, use_base);
+       chash_mid(type, use_base, innerkey);
+       chash_end(type, use_base, sub[2], Ustrlen(sub[2]), innerhash);
 
-      chash_start(type, use_base);
-      chash_mid(type, use_base, outerkey);
-      chash_end(type, use_base, innerhash, hashlen, finalhash);
+       chash_start(type, use_base);
+       chash_mid(type, use_base, outerkey);
+       chash_end(type, use_base, innerhash, hashlen, finalhash);
 
-      /* Encode the final hash as a hex string */
+       /* Encode the final hash as a hex string */
 
-      p = finalhash_hex;
-      for (i = 0; i < hashlen; i++)
-        {
-        *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
-        *p++ = hex_digits[finalhash[i] & 0x0f];
-        }
+       p = finalhash_hex;
+       for (i = 0; i < hashlen; i++)
+         {
+         *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
+         *p++ = hex_digits[finalhash[i] & 0x0f];
+         }
 
-      DEBUG(D_any) debug_printf("HMAC[%s](%.*s,%.*s)=%.*s\n", sub[0],
-        (int)keylen, keyptr, Ustrlen(sub[2]), sub[2], hashlen*2, finalhash_hex);
+       DEBUG(D_any) debug_printf("HMAC[%s](%.*s,%s)=%.*s\n",
+         sub[0], (int)keylen, keyptr, sub[2], hashlen*2, finalhash_hex);
 
-      yield = string_catn(yield, &size, &ptr, finalhash_hex, hashlen*2);
+       yield = string_catn(yield, &size, &ptr, finalhash_hex, hashlen*2);
+       }
+      continue;
       }
 
-    continue;
-
     /* Handle global substitution for "sg" - like Perl's s/xxx/yyy/g operator.
     We have to save the numerical variables and restore them afterwards. */
 
@@ -6256,6 +6266,47 @@ while (*s != 0)
 
     switch(c)
       {
+      case EOP_BASE32:
+       {
+        uschar *t;
+        unsigned long int n = Ustrtoul(sub, &t, 10);
+       uschar * s = NULL;
+       int sz = 0, i = 0;
+
+        if (*t != 0)
+          {
+          expand_string_message = string_sprintf("argument for base32 "
+            "operator is \"%s\", which is not a decimal number", sub);
+          goto EXPAND_FAILED;
+          }
+       for ( ; n; n >>= 5)
+         s = string_catn(s, &sz, &i, &base32_chars[n & 0x1f], 1);
+
+       while (i > 0) yield = string_catn(yield, &size, &ptr, &s[--i], 1);
+       continue;
+       }
+
+      case EOP_BASE32D:
+        {
+        uschar *tt = sub;
+        unsigned long int n = 0;
+       uschar * s;
+        while (*tt)
+          {
+          uschar * t = Ustrchr(base32_chars, *tt++);
+          if (t == NULL)
+            {
+            expand_string_message = string_sprintf("argument for base32d "
+              "operator is \"%s\", which is not a base 32 number", sub);
+            goto EXPAND_FAILED;
+            }
+          n = n * 32 + (t - base32_chars);
+          }
+        s = string_sprintf("%ld", n);
+        yield = string_cat(yield, &size, &ptr, s);
+        continue;
+        }
+
       case EOP_BASE62:
         {
         uschar *t;
index 8d47a0d..8745a39 100644 (file)
@@ -438,7 +438,6 @@ extern int     string_is_ip_address(const uschar *, int *);
 #ifdef SUPPORT_I18N
 extern BOOL    string_is_utf8(const uschar *);
 #endif
-extern uschar *string_log_address(address_item *, BOOL, BOOL);
 extern uschar *string_nextinlist(const uschar **, int *, uschar *, int);
 extern uschar *string_open_failed(int, const char *, ...) PRINTF_FUNCTION(2,3);
 extern const uschar *string_printing2(const uschar *, BOOL);
index a0f0226..f468d23 100644 (file)
@@ -115,28 +115,47 @@ pdkim_combined_canon_entry pdkim_combined_canons[] = {
 const char *
 pdkim_verify_status_str(int status)
 {
-  switch(status) {
-    case PDKIM_VERIFY_NONE:    return "PDKIM_VERIFY_NONE";
-    case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
-    case PDKIM_VERIFY_FAIL:    return "PDKIM_VERIFY_FAIL";
-    case PDKIM_VERIFY_PASS:    return "PDKIM_VERIFY_PASS";
-    default:                   return "PDKIM_VERIFY_UNKNOWN";
+switch(status)
+  {
+  case PDKIM_VERIFY_NONE:    return "PDKIM_VERIFY_NONE";
+  case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
+  case PDKIM_VERIFY_FAIL:    return "PDKIM_VERIFY_FAIL";
+  case PDKIM_VERIFY_PASS:    return "PDKIM_VERIFY_PASS";
+  default:                   return "PDKIM_VERIFY_UNKNOWN";
   }
 }
 
 const char *
 pdkim_verify_ext_status_str(int ext_status)
 {
-  switch(ext_status) {
-    case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
-    case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
-    case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
-    case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
-    case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
-    case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
-    case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
-    case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
-    default: return "PDKIM_VERIFY_UNKNOWN";
+switch(ext_status)
+  {
+  case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
+  case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
+  case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
+  case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
+  case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
+  case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
+  case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
+  case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
+  default: return "PDKIM_VERIFY_UNKNOWN";
+  }
+}
+
+const char *
+pdkim_errstr(int status)
+{
+switch(status)
+  {
+  case PDKIM_OK:               return "OK";
+  case PDKIM_FAIL:             return "FAIL";
+  case PDKIM_ERR_RSA_PRIVKEY:  return "RSA_PRIVKEY";
+  case PDKIM_ERR_RSA_SIGNING:  return "RSA SIGNING";
+  case PDKIM_ERR_LONG_LINE:    return "RSA_LONG_LINE";
+  case PDKIM_ERR_BUFFER_TOO_SMALL:     return "BUFFER_TOO_SMALL";
+  case PDKIM_SIGN_PRIVKEY_WRAP:        return "PRIVKEY_WRAP";
+  case PDKIM_SIGN_PRIVKEY_B64D:        return "PRIVKEY_B64D";
+  default: return "(unknown)";
   }
 }
 
index 0803ea0..5d0157e 100644 (file)
@@ -304,6 +304,9 @@ int        pdkim_feed_finish  (pdkim_ctx *, pdkim_signature **);
 DLLEXPORT
 void       pdkim_free_ctx     (pdkim_ctx *);
 
+
+const char *   pdkim_errstr(int);
+
 #ifdef __cplusplus
 }
 #endif
index 3b04825..6a8ce88 100644 (file)
@@ -3820,9 +3820,10 @@ size = 256;
 sptr = 0;
 s = store_get(size);
 
-s = string_append(s, &size, &sptr, 2, US"<= ",
-  (sender_address[0] == 0)? US"<>" : sender_address);
-if (message_reference != NULL)
+s = string_append(s, &size, &sptr, 2,
+  fake_response == FAIL ? US"(= " : US"<= ",
+  sender_address[0] == 0 ? US"<>" : sender_address);
+if (message_reference)
   s = string_append(s, &size, &sptr, 2, US" R=", message_reference);
 
 s = add_host_info_for_log(s, &size, &sptr);
@@ -3832,7 +3833,7 @@ if (LOGGING(tls_cipher) && tls_in.cipher)
   s = string_append(s, &size, &sptr, 2, US" X=", tls_in.cipher);
 if (LOGGING(tls_certificate_verified) && tls_in.cipher)
   s = string_append(s, &size, &sptr, 2, US" CV=",
-    tls_in.certificate_verified? "yes":"no");
+    tls_in.certificate_verified ? "yes":"no");
 if (LOGGING(tls_peerdn) && tls_in.peerdn)
   s = string_append(s, &size, &sptr, 3, US" DN=\"",
     string_printing(tls_in.peerdn), US"\"");
@@ -3844,10 +3845,10 @@ if (LOGGING(tls_sni) && tls_in.sni)
 if (sender_host_authenticated)
   {
   s = string_append(s, &size, &sptr, 2, US" A=", sender_host_authenticated);
-  if (authenticated_id != NULL)
+  if (authenticated_id)
     {
     s = string_append(s, &size, &sptr, 2, US":", authenticated_id);
-    if (LOGGING(smtp_mailauth) && authenticated_sender != NULL)
+    if (LOGGING(smtp_mailauth) && authenticated_sender)
       s = string_append(s, &size, &sptr, 2, US":", authenticated_sender);
     }
   }
@@ -3886,7 +3887,7 @@ any characters except " \ and CR and so in particular it can contain NL!
 Therefore, make sure we use a printing-characters only version for the log.
 Also, allow for domain literals in the message id. */
 
-if (msgid_header != NULL)
+if (msgid_header)
   {
   uschar *old_id;
   BOOL save_allow_domain_literals = allow_domain_literals;
@@ -3969,7 +3970,9 @@ if (message_logs && blackholed_by == NULL)
       if (deliver_freeze) fprintf(message_log, "%s frozen by %s\n", now,
         frozen_by);
       if (queue_only_policy) fprintf(message_log,
-        "%s no immediate delivery: queued by %s\n", now, queued_by);
+        "%s no immediate delivery: queued%s%s by %s\n", now,
+        *queue_name ? " in " : "", *queue_name ? CS queue_name : "",
+       queued_by);
       (void)fclose(message_log);
       }
     }
@@ -4089,7 +4092,9 @@ if(!smtp_reply)
 
   if (deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by);
   if (queue_only_policy) log_write(L_delay_delivery, LOG_MAIN,
-    "no immediate delivery: queued by %s", queued_by);
+    "no immediate delivery: queued%s%s by %s",
+    *queue_name ? " in " : "", *queue_name ? CS queue_name : "",       
+    queued_by);
   }
 receive_call_bombout = FALSE;
 
@@ -4145,15 +4150,15 @@ if (smtp_input)
 
   if (!smtp_batched_input)
     {
-    if (smtp_reply == NULL)
+    if (!smtp_reply)
       {
       if (fake_response != OK)
-        smtp_respond((fake_response == DEFER)? US"450" : US"550", 3, TRUE,
-          fake_response_text);
+        smtp_respond(fake_response == DEFER ? US"450" : US"550",
+         3, TRUE, fake_response_text);
 
       /* An OK response is required; use "message" text if present. */
 
-      else if (user_msg != NULL)
+      else if (user_msg)
         {
         uschar *code = US"250";
         int len = 3;
@@ -4207,7 +4212,8 @@ if (smtp_input)
   nothing on success. The function moan_smtp_batch() does not return -
   it exits from the program with a non-zero return code. */
 
-  else if (smtp_reply != NULL) moan_smtp_batch(NULL, "%s", smtp_reply);
+  else if (smtp_reply)
+    moan_smtp_batch(NULL, "%s", smtp_reply);
   }
 
 
@@ -4216,7 +4222,7 @@ file has already been unlinked, and the header file was never written to disk.
 We must now indicate that nothing was received, to prevent a delivery from
 starting. */
 
-if (blackholed_by != NULL)
+if (blackholed_by)
   {
   const uschar *detail = local_scan_data
     ? string_printing(local_scan_data)
index 963948f..ad074e3 100644 (file)
@@ -1544,177 +1544,6 @@ return (eno == EACCES)?
 
 
 
-#ifndef COMPILE_UTILITY
-/*************************************************
-*        Generate local prt for logging          *
-*************************************************/
-
-/* This function is a subroutine for use in string_log_address() below.
-
-Arguments:
-  addr        the address being logged
-  yield       the current dynamic buffer pointer
-  sizeptr     points to current size
-  ptrptr      points to current insert pointer
-
-Returns:      the new value of the buffer pointer
-*/
-
-static uschar *
-string_get_localpart(address_item *addr, uschar *yield, int *sizeptr,
-  int *ptrptr)
-{
-uschar * s;
-
-s = addr->prefix;
-if (testflag(addr, af_include_affixes) && s)
-  {
-#ifdef SUPPORT_I18N
-  if (testflag(addr, af_utf8_downcvt))
-    s = string_localpart_utf8_to_alabel(s, NULL);
-#endif
-  yield = string_cat(yield, sizeptr, ptrptr, s);
-  }
-
-s = addr->local_part;
-#ifdef SUPPORT_I18N
-if (testflag(addr, af_utf8_downcvt))
-  s = string_localpart_utf8_to_alabel(s, NULL);
-#endif
-yield = string_cat(yield, sizeptr, ptrptr, s);
-
-s = addr->suffix;
-if (testflag(addr, af_include_affixes) && s)
-  {
-#ifdef SUPPORT_I18N
-  if (testflag(addr, af_utf8_downcvt))
-    s = string_localpart_utf8_to_alabel(s, NULL);
-#endif
-  yield = string_cat(yield, sizeptr, ptrptr, s);
-  }
-
-return yield;
-}
-
-
-/*************************************************
-*          Generate log address list             *
-*************************************************/
-
-/* This function generates a list consisting of an address and its parents, for
-use in logging lines. For saved onetime aliased addresses, the onetime parent
-field is used. If the address was delivered by a transport with rcpt_include_
-affixes set, the af_include_affixes bit will be set in the address. In that
-case, we include the affixes here too.
-
-Arguments:
-  addr          bottom (ultimate) address
-  all_parents   if TRUE, include all parents
-  success       TRUE for successful delivery
-
-Returns:        a string in dynamic store
-*/
-
-uschar *
-string_log_address(address_item *addr, BOOL all_parents, BOOL success)
-{
-int size = 64;
-int ptr = 0;
-BOOL add_topaddr = TRUE;
-uschar *yield = store_get(size);
-address_item *topaddr;
-
-/* Find the ultimate parent */
-
-for (topaddr = addr; topaddr->parent != NULL; topaddr = topaddr->parent);
-
-/* We start with just the local part for pipe, file, and reply deliveries, and
-for successful local deliveries from routers that have the log_as_local flag
-set. File deliveries from filters can be specified as non-absolute paths in
-cases where the transport is goin to complete the path. If there is an error
-before this happens (expansion failure) the local part will not be updated, and
-so won't necessarily look like a path. Add extra text for this case. */
-
-if (testflag(addr, af_pfr) ||
-      (success &&
-       addr->router != NULL && addr->router->log_as_local &&
-       addr->transport != NULL && addr->transport->info->local))
-  {
-  if (testflag(addr, af_file) && addr->local_part[0] != '/')
-    yield = string_catn(yield, &size, &ptr, CUS"save ", 5);
-  yield = string_get_localpart(addr, yield, &size, &ptr);
-  }
-
-/* Other deliveries start with the full address. It we have split it into local
-part and domain, use those fields. Some early failures can happen before the
-splitting is done; in those cases use the original field. */
-
-else
-  {
-  if (addr->local_part != NULL)
-    {
-    const uschar * s;
-    yield = string_get_localpart(addr, yield, &size, &ptr);
-    yield = string_catn(yield, &size, &ptr, US"@", 1);
-    s = addr->domain;
-#ifdef SUPPORT_I18N
-    if (testflag(addr, af_utf8_downcvt))
-      s = string_localpart_utf8_to_alabel(s, NULL);
-#endif
-    yield = string_cat(yield, &size, &ptr, s);
-    }
-  else
-    yield = string_cat(yield, &size, &ptr, addr->address);
-  yield[ptr] = 0;
-
-  /* If the address we are going to print is the same as the top address,
-  and all parents are not being included, don't add on the top address. First
-  of all, do a caseless comparison; if this succeeds, do a caseful comparison
-  on the local parts. */
-
-  if (strcmpic(yield, topaddr->address) == 0 &&
-      Ustrncmp(yield, topaddr->address, Ustrchr(yield, '@') - yield) == 0 &&
-      addr->onetime_parent == NULL &&
-      (!all_parents || addr->parent == NULL || addr->parent == topaddr))
-    add_topaddr = FALSE;
-  }
-
-/* If all parents are requested, or this is a local pipe/file/reply, and
-there is at least one intermediate parent, show it in brackets, and continue
-with all of them if all are wanted. */
-
-if ((all_parents || testflag(addr, af_pfr)) &&
-    addr->parent != NULL &&
-    addr->parent != topaddr)
-  {
-  uschar *s = US" (";
-  address_item *addr2;
-  for (addr2 = addr->parent; addr2 != topaddr; addr2 = addr2->parent)
-    {
-    yield = string_catn(yield, &size, &ptr, s, 2);
-    yield = string_cat (yield, &size, &ptr, addr2->address);
-    if (!all_parents) break;
-    s = US", ";
-    }
-  yield = string_catn(yield, &size, &ptr, US")", 1);
-  }
-
-/* Add the top address if it is required */
-
-if (add_topaddr)
-  {
-  yield = string_catn(yield, &size, &ptr, US" <", 2);
-
-  yield = string_cat(yield, &size, &ptr,
-    addr->onetime_parent ? addr->onetime_parent : topaddr->address);
-
-  yield = string_catn(yield, &size, &ptr, US">", 1);
-  }
-
-yield[ptr] = 0;  /* string_cat() leaves space */
-return yield;
-}
-#endif  /* COMPILE_UTILITY */
 
 
 #ifndef COMPILE_UTILITY
index 88d925e..a68c22f 100644 (file)
@@ -616,13 +616,8 @@ Arguments:
   addr                  (chain of) addresses (for extra headers), or NULL;
                           only the first address is used
   fd                    file descriptor to write the message to
+  tctx                  transport context
   sendfn               function for output (transport or verify)
-  wck_flags
-    use_crlf           turn NL into CR LF
-    use_bdat           callback before chunk flush
-  rewrite_rules         chain of header rewriting rules
-  rewrite_existflags    flags for the rewriting rules
-  chunk_cb             transport callback function for data-chunk commands
 
 Returns:                TRUE on success; FALSE on failure.
 */
@@ -1228,6 +1223,7 @@ set up a filtering process, fork another process to call the internal function
 to write to the filter, and in this process just suck from the filter and write
 down the given fd. At the end, tidy up the pipes and the processes.
 
+XXX
 Arguments:     as for internal_transport_write_message() above
 
 Returns:       TRUE on success; FALSE (with errno) for any failure
index 25e4934..52b2b91 100644 (file)
@@ -1223,7 +1223,8 @@ switch (dns_lookup(dnsa, buffer, T_TLSA, &fullname))
   case DNS_AGAIN:
     return DEFER; /* just defer this TLS'd conn */
 
-  case DNS_NOMATCH:
+  case DNS_NODATA:     /* no TLSA RR for this lookup */
+  case DNS_NOMATCH:    /* no records at all for this lookup */
     return dane_required ? FAIL : FAIL_FORCED;
 
   default:
@@ -2483,7 +2484,7 @@ else
     | (tblock->headers_only    ? topt_no_body : 0)
     | (tblock->return_path_add ? topt_add_return_path : 0)
     | (tblock->delivery_date_add ? topt_add_delivery_date : 0)
-    | (tblock->envelope_to_add ? topt_add_envelope_to : 0),
+    | (tblock->envelope_to_add ? topt_add_envelope_to : 0)
   };
 
   /* If using CHUNKING we need a callback from the generic transport
index e223bd4..29d71cd 100644 (file)
@@ -1,2 +1,2 @@
-1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-smtp S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 (= CALLER@myhost.test.ex U=CALLER P=local-smtp S=sss
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-smtp S=sss
index 1ab5847..c1176fe 100644 (file)
@@ -1,6 +1,6 @@
 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss id=41C2F849.3060203@projectile.test.ex
 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@myhost.test.ex U=CALLER P=local-esmtp S=sss id=41C2F849.3060203@projectile.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 (= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss id=41C2F849.3060203@projectile.test.ex
 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
index 278a386..dafcba7 100644 (file)
@@ -179,6 +179,20 @@ hex2b64:${hex2b64:1a2b3c4d5e6g}
 hex2b64:${hex2b64:${md5:the quick brown fox}}
 hex2b64:${hex2b64:${sha1:the quick brown fox}}
 
+base32: 0  <${base32:0}>
+base32: 1  <${base32:1}>
+base32: 31 <${base32:31}>
+base32: 32 <${base32:32}>
+base32: 42 <${base32:42}>
+base32 error: 0x1 ${base32:0x1}
+
+base32d: 0  ${base32d:${base32:0}}
+base32d: 1  ${base32d:${base32:1}}
+base32d: 31 ${base32d:${base32:31}}
+base32d: 32 ${base32d:${base32:32}}
+base32d: 42 ${base32d:${base32:42}}
+base32d error: ABC ${base32d:ABC}
+
 The base62 operator is actually a base36 operator in the Darwin and Cygwin
 environments. Write cunning tests that produce the same output in both cases,
 while doing a reasonable check.
index 947f169..c351136 100644 (file)
@@ -1,4 +1,4 @@
-# Long lines for fakedefer/fakereject
+# Long response lines for fakedefer/fakereject
 exim -bs
 mail from:<>
 rcpt to:<userx@test.ex>
index 19ed347..317b4bd 100644 (file)
@@ -11,8 +11,8 @@ considering: abcd}{\N^([ab]+)(\w+)$\N}{$2$1}fail}
 considering: \N^([ab]+)(\w+)$\N}{$2$1}fail}
   expanding: \N^([ab]+)(\w+)$\N
      result: ^([ab]+)(\w+)$
-condition: match{abcd}{\N^([ab]+)(\w+)$\N}
-   result: true
+  condition: match{abcd}{\N^([ab]+)(\w+)$\N}
+     result: true
 considering: $2$1}fail}
   expanding: $2$1
      result: cdab
@@ -25,8 +25,8 @@ considering: wxyz}{\N^([ab]+)(\w+)$\N}{$2$1}fail}
 considering: \N^([ab]+)(\w+)$\N}{$2$1}fail}
   expanding: \N^([ab]+)(\w+)$\N
      result: ^([ab]+)(\w+)$
-condition: match{wxyz}{\N^([ab]+)(\w+)$\N}
-   result: false
+  condition: match{wxyz}{\N^([ab]+)(\w+)$\N}
+     result: false
    scanning: $2$1}fail}
   expanding: $2$1
      result: 
@@ -41,8 +41,8 @@ considering: 1}{1}{yes}{${lookup{xx}lsearch{/non/exist}}}}
 considering: 1}{yes}{${lookup{xx}lsearch{/non/exist}}}}
   expanding: 1
      result: 1
-condition: eq {1}{1}
-   result: true
+  condition: eq {1}{1}
+     result: true
 considering: yes}{${lookup{xx}lsearch{/non/exist}}}}
   expanding: yes
      result: yes
@@ -69,8 +69,8 @@ considering: a.b.c}{yes}{no}}
      result: a.b.c
 LOG: MAIN PANIC
   no @ found in the subject of an address list match: subject="a.b.c" pattern="a.b.c"
-condition: match_address{a.b.c}{a.b.c}
-   result: false
+  condition: match_address{a.b.c}{a.b.c}
+     result: false
    scanning: yes}{no}}
   expanding: yes
      result: yes
@@ -147,8 +147,8 @@ considering: black}{white}{$sender_host_name}{No}}
 considering: white}{$sender_host_name}{No}}
   expanding: white
      result: white
-condition: eq{black}{white}
-   result: false
+  condition: eq{black}{white}
+     result: false
    scanning: $sender_host_name}{No}}
   expanding: $sender_host_name
      result: 
index e763efc..197256b 100644 (file)
@@ -57,8 +57,8 @@ considering: V4NET.0.0.1} {$sender_host_address} {2} {30}}s
 considering: $sender_host_address} {2} {30}}s
   expanding: $sender_host_address
      result: V4NET.0.0.1
-condition: eq {V4NET.0.0.1} {$sender_host_address}
-   result: true
+  condition: eq {V4NET.0.0.1} {$sender_host_address}
+     result: true
 considering: 2} {30}}s
   expanding: 2
      result: 2
index 673d9e6..941e8f8 100644 (file)
@@ -27,7 +27,7 @@ lock file created
 mailbox TESTSUITE/test-mail/userx is locked
 writing to file TESTSUITE/test-mail/userx
 writing data block fd=dddd size=sss timeout=0
-process pppp running as transport filter: fd_write=10 fd_read=11
+process pppp running as transport filter: fd_write=9 fd_read=10
 writing data block fd=dddd size=sss timeout=0
 process pppp writing to transport filter
 copying from the filter
index 9f95393..24a4fcd 100644 (file)
@@ -49,8 +49,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -69,8 +69,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -87,8 +87,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: false
+  condition: def:sender_helo_name
+     result: false
    scanning: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -103,8 +103,8 @@ condition: def:sender_helo_name
   expanding: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}
      result: from CALLER 
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -112,8 +112,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -121,8 +133,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@test.ex>)
        
-condition: def:received_for
-   result: false
+  condition: def:received_for
+     result: false
    scanning: 
        for $received_for}}
   expanding: 
@@ -465,8 +477,8 @@ mailbox TESTSUITE/test-mail/junk is locked
 writing to file TESTSUITE/test-mail/junk
 considering: From ${if def:return_path{$return_path}{MAILER-DAEMON}} ${tod_bsdinbox}
 
-condition: def:return_path
-   result: true
+  condition: def:return_path
+     result: true
 considering: $return_path}{MAILER-DAEMON}} ${tod_bsdinbox}
 
   expanding: $return_path
@@ -520,8 +532,8 @@ mailbox TESTSUITE/test-mail/junk is locked
 writing to file TESTSUITE/test-mail/junk
 considering: From ${if def:return_path{$return_path}{MAILER-DAEMON}} ${tod_bsdinbox}
 
-condition: def:return_path
-   result: true
+  condition: def:return_path
+     result: true
 considering: $return_path}{MAILER-DAEMON}} ${tod_bsdinbox}
 
   expanding: $return_path
index a95583a..f950e45 100644 (file)
@@ -11,8 +11,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -31,8 +31,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -49,8 +49,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: false
+  condition: def:sender_helo_name
+     result: false
    scanning: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -65,8 +65,8 @@ condition: def:sender_helo_name
   expanding: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}
      result: from CALLER 
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -74,8 +74,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -83,8 +95,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@test.ex>)
        
-condition: def:received_for
-   result: false
+  condition: def:received_for
+     result: false
    scanning: 
        for $received_for}}
   expanding: 
@@ -138,8 +150,8 @@ considering: $h_auto-submitted:}{(?i)auto-generated|auto-replied} }} {no}{yes}}
 considering: (?i)auto-generated|auto-replied} }} {no}{yes}}
   expanding: (?i)auto-generated|auto-replied
      result: (?i)auto-generated|auto-replied
-condition: or {{ !eq{$h_list-id:$h_list-post:$h_list-subscribe:}{} }{ match{$h_precedence:}{(?i)bulk|list|junk} }{ match{$h_auto-submitted:}{(?i)auto-generated|auto-replied} }}
-   result: false
+  condition: or {{ !eq{$h_list-id:$h_list-post:$h_list-subscribe:}{} }{ match{$h_precedence:}{(?i)bulk|list|junk} }{ match{$h_auto-submitted:}{(?i)auto-generated|auto-replied} }}
+     result: false
    scanning: no}{yes}}
   expanding: no
      result: no
@@ -169,8 +181,8 @@ considering: +dlist}}
 considering: $domain
   expanding: $domain
      result: ehlo.domain
-condition: match_domain {$sender_helo_name}{+dlist}
-   result: true
+  condition: match_domain {$sender_helo_name}{+dlist}
+     result: true
   expanding: ${if match_domain {$sender_helo_name}{+dlist}}
      result: true
 considering: domain=$domain/sender_domain=$sender_address_domain
diff --git a/test/stderr/4504 b/test/stderr/4504
new file mode 100644 (file)
index 0000000..045fadc
--- /dev/null
@@ -0,0 +1,2 @@
+
+******** SERVER ********
index f455075..fe3ed44 100644 (file)
@@ -18,8 +18,8 @@ considering: SERVER}{server}{queue}{cutthrough}}
 considering: server}{queue}{cutthrough}}
   expanding: server
      result: server
-condition: eq {SERVER}{server}
-   result: false
+  condition: eq {SERVER}{server}
+     result: false
    scanning: queue}{cutthrough}}
   expanding: queue
      result: queue
@@ -69,8 +69,8 @@ considering: $address_data}{usery}{*}{:}}
 considering: usery}{*}{:}}
   expanding: usery
      result: usery
-condition: eq {$address_data}{usery}
-   result: false
+  condition: eq {$address_data}{usery}
+     result: false
    scanning: *}{:}}
   expanding: *
      result: *
@@ -88,8 +88,8 @@ considering: $address_data}{userz}{*}{:}}
 considering: userz}{*}{:}}
   expanding: userz
      result: userz
-condition: eq {$address_data}{userz}
-   result: false
+  condition: eq {$address_data}{userz}
+     result: false
    scanning: *}{:}}
   expanding: *
      result: *
@@ -134,8 +134,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -154,8 +154,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -172,8 +172,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: true
+  condition: def:sender_helo_name
+     result: true
 considering: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -188,8 +188,8 @@ considering: (helo=$sender_helo_name)
        }}
      result: from CALLER (helo=myhost.test.ex)
        
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -197,8 +197,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local-esmtp
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -206,8 +218,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@myhost.test.ex>)
        
-condition: def:received_for
-   result: true
+  condition: def:received_for
+     result: true
 considering: 
        for $received_for}}
   expanding: 
@@ -264,8 +276,8 @@ considering: SERVER}{server}{queue}{cutthrough}}
 considering: server}{queue}{cutthrough}}
   expanding: server
      result: server
-condition: eq {SERVER}{server}
-   result: false
+  condition: eq {SERVER}{server}
+     result: false
    scanning: queue}{cutthrough}}
   expanding: queue
      result: queue
@@ -315,8 +327,8 @@ considering: $address_data}{usery}{*}{:}}
 considering: usery}{*}{:}}
   expanding: usery
      result: usery
-condition: eq {$address_data}{usery}
-   result: true
+  condition: eq {$address_data}{usery}
+     result: true
 considering: *}{:}}
   expanding: *
      result: *
@@ -349,8 +361,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -369,8 +381,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -387,8 +399,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: true
+  condition: def:sender_helo_name
+     result: true
 considering: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -403,8 +415,8 @@ considering: (helo=$sender_helo_name)
        }}
      result: from CALLER (helo=myhost.test.ex)
        
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -412,8 +424,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local-esmtp
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -421,8 +445,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@myhost.test.ex>)
        
-condition: def:received_for
-   result: true
+  condition: def:received_for
+     result: true
 considering: 
        for $received_for}}
   expanding: 
@@ -479,8 +503,8 @@ considering: SERVER}{server}{queue}{cutthrough}}
 considering: server}{queue}{cutthrough}}
   expanding: server
      result: server
-condition: eq {SERVER}{server}
-   result: false
+  condition: eq {SERVER}{server}
+     result: false
    scanning: queue}{cutthrough}}
   expanding: queue
      result: queue
@@ -530,8 +554,8 @@ considering: $address_data}{usery}{*}{:}}
 considering: usery}{*}{:}}
   expanding: usery
      result: usery
-condition: eq {$address_data}{usery}
-   result: true
+  condition: eq {$address_data}{usery}
+     result: true
 considering: *}{:}}
   expanding: *
      result: *
@@ -564,8 +588,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -584,8 +608,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -602,8 +626,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: true
+  condition: def:sender_helo_name
+     result: true
 considering: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -618,8 +642,8 @@ considering: (helo=$sender_helo_name)
        }}
      result: from CALLER (helo=myhost.test.ex)
        
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -627,8 +651,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local-esmtp
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -636,8 +672,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@myhost.test.ex>)
        
-condition: def:received_for
-   result: true
+  condition: def:received_for
+     result: true
 considering: 
        for $received_for}}
   expanding: 
index 9117875..623b998 100644 (file)
@@ -18,8 +18,8 @@ considering: SERVER}{server}{queue}{cutthrough}}
 considering: server}{queue}{cutthrough}}
   expanding: server
      result: server
-condition: eq {SERVER}{server}
-   result: false
+  condition: eq {SERVER}{server}
+     result: false
    scanning: queue}{cutthrough}}
   expanding: queue
      result: queue
@@ -69,8 +69,8 @@ considering: $address_data}{usery}{*}{:}}
 considering: usery}{*}{:}}
   expanding: usery
      result: usery
-condition: eq {$address_data}{usery}
-   result: false
+  condition: eq {$address_data}{usery}
+     result: false
    scanning: *}{:}}
   expanding: *
      result: *
@@ -88,8 +88,8 @@ considering: $address_data}{userz}{*}{:}}
 considering: userz}{*}{:}}
   expanding: userz
      result: userz
-condition: eq {$address_data}{userz}
-   result: false
+  condition: eq {$address_data}{userz}
+     result: false
    scanning: *}{:}}
   expanding: *
      result: *
@@ -133,8 +133,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -153,8 +153,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -171,8 +171,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: true
+  condition: def:sender_helo_name
+     result: true
 considering: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -187,8 +187,8 @@ considering: (helo=$sender_helo_name)
        }}
      result: from CALLER (helo=myhost.test.ex)
        
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -196,8 +196,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local-esmtp
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -205,8 +217,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@myhost.test.ex>)
        
-condition: def:received_for
-   result: true
+  condition: def:received_for
+     result: true
 considering: 
        for $received_for}}
   expanding: 
@@ -263,8 +275,8 @@ considering: SERVER}{server}{queue}{cutthrough}}
 considering: server}{queue}{cutthrough}}
   expanding: server
      result: server
-condition: eq {SERVER}{server}
-   result: false
+  condition: eq {SERVER}{server}
+     result: false
    scanning: queue}{cutthrough}}
   expanding: queue
      result: queue
@@ -314,8 +326,8 @@ considering: $address_data}{usery}{*}{:}}
 considering: usery}{*}{:}}
   expanding: usery
      result: usery
-condition: eq {$address_data}{usery}
-   result: true
+  condition: eq {$address_data}{usery}
+     result: true
 considering: *}{:}}
   expanding: *
      result: *
@@ -348,8 +360,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -368,8 +380,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -386,8 +398,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: true
+  condition: def:sender_helo_name
+     result: true
 considering: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -402,8 +414,8 @@ considering: (helo=$sender_helo_name)
        }}
      result: from CALLER (helo=myhost.test.ex)
        
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -411,8 +423,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local-esmtp
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -420,8 +444,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@myhost.test.ex>)
        
-condition: def:received_for
-   result: true
+  condition: def:received_for
+     result: true
 considering: 
        for $received_for}}
   expanding: 
@@ -478,8 +502,8 @@ considering: SERVER}{server}{queue}{cutthrough}}
 considering: server}{queue}{cutthrough}}
   expanding: server
      result: server
-condition: eq {SERVER}{server}
-   result: false
+  condition: eq {SERVER}{server}
+     result: false
    scanning: queue}{cutthrough}}
   expanding: queue
      result: queue
@@ -529,8 +553,8 @@ considering: $address_data}{usery}{*}{:}}
 considering: usery}{*}{:}}
   expanding: usery
      result: usery
-condition: eq {$address_data}{usery}
-   result: true
+  condition: eq {$address_data}{usery}
+     result: true
 considering: *}{:}}
   expanding: *
      result: *
@@ -563,8 +587,8 @@ considering: Received: ${if def:sender_rcvhost {from $sender_rcvhost
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_rcvhost
-   result: false
+  condition: def:sender_rcvhost
+     result: false
    scanning: from $sender_rcvhost
        }{${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
@@ -583,8 +607,8 @@ considering: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${i
        ${if def:sender_address {(envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
-condition: def:sender_ident
-   result: true
+  condition: def:sender_ident
+     result: true
 considering: from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -601,8 +625,8 @@ considering: $sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name
      result: CALLER
   expanding: from ${quote_local_part:$sender_ident} 
      result: from CALLER 
-condition: def:sender_helo_name
-   result: true
+  condition: def:sender_helo_name
+     result: true
 considering: (helo=$sender_helo_name)
        }}}}by $primary_hostname ${if def:received_protocol {with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
@@ -617,8 +641,8 @@ considering: (helo=$sender_helo_name)
        }}
      result: from CALLER (helo=myhost.test.ex)
        
-condition: def:received_protocol
-   result: true
+  condition: def:received_protocol
+     result: true
 considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        }}(Exim $version_number)
        ${if def:sender_address {(envelope-from <$sender_address>)
@@ -626,8 +650,20 @@ considering: with $received_protocol}} ${if def:tls_cipher {($tls_cipher)
        for $received_for}}
   expanding: with $received_protocol
      result: with local-esmtp
-condition: def:sender_address
-   result: true
+  condition: def:tls_cipher
+     result: false
+   scanning: ($tls_cipher)
+       }}(Exim $version_number)
+       ${if def:sender_address {(envelope-from <$sender_address>)
+       }}id $message_exim_id${if def:received_for {
+       for $received_for}}
+  expanding: ($tls_cipher)
+       
+     result: ()
+       
+   skipping: result is not used
+  condition: def:sender_address
+     result: true
 considering: (envelope-from <$sender_address>)
        }}id $message_exim_id${if def:received_for {
        for $received_for}}
@@ -635,8 +671,8 @@ considering: (envelope-from <$sender_address>)
        
      result: (envelope-from <CALLER@myhost.test.ex>)
        
-condition: def:received_for
-   result: true
+  condition: def:received_for
+     result: true
 considering: 
        for $received_for}}
   expanding: 
index 0bbd4c7..a19cc52 100644 (file)
 > hex2b64:MPPJPkZDbetYunCBao7BJA==
 > hex2b64:ztcfpyNSMb7Tg/rP3EHE3cwi7PE=
 > 
+> base32: 0  <>
+> base32: 1  <b>
+> base32: 31 <7>
+> base32: 32 <ba>
+> base32: 42 <bk>
+> Failed: argument for base32 operator is "0x1", which is not a decimal number
+> 
+> base32d: 0  0
+> base32d: 1  1
+> base32d: 31 31
+> base32d: 32 32
+> base32d: 42 42
+> Failed: argument for base32d operator is "ABC", which is not a base 32 number
+> 
 > The base62 operator is actually a base36 operator in the Darwin and Cygwin
 > environments. Write cunning tests that produce the same output in both cases,
 > while doing a reasonable check.