Merge branch 'fakereject'
authorJeremy Harris <jgh146exb@wizmail.org>
Thu, 4 Aug 2016 14:26:05 +0000 (15:26 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Thu, 4 Aug 2016 14:26:05 +0000 (15:26 +0100)
40 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/queue.c
src/src/receive.c
src/src/structs.h
src/src/transport.c
src/src/transports/appendfile.c
src/src/transports/autoreply.c
src/src/transports/lmtp.c
src/src/transports/pipe.c
src/src/transports/smtp.c
src/src/transports/smtp.h
src/src/verify.c
test/log/0217
test/log/0218
test/log/0322
test/log/0495
test/log/0497
test/log/0552
test/scripts/0000-Basic/0002
test/scripts/0000-Basic/0217
test/stderr/0002
test/stderr/0092
test/stderr/0218
test/stderr/0393
test/stderr/0402
test/stderr/0495
test/stderr/0544
test/stderr/4504 [new file with mode: 0644]
test/stderr/5410
test/stderr/5420
test/stdout/0002
test/stdout/0217

index 152bcb2..7bd5b7f 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"
@@ -19873,12 +19888,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.
 
@@ -31524,7 +31544,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,
@@ -38059,7 +38079,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
@@ -38116,7 +38136,7 @@ used.
 .section "Verifying DKIM signatures in incoming mail" "SECID514"
 .cindex "DKIM" "verification"
 
-Verification of DKIM signatures in incoming email is implemented via the
+Verification of DKIM signatures in SMTP incoming email is implemented via the
 &%acl_smtp_dkim%& ACL. By default, this ACL is called once for each
 syntactically(!) correct signature in the incoming message.
 A missing ACL definition defaults to accept.
index 454d343..11b25f8 100644 (file)
@@ -55,7 +55,17 @@ 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 Fakereject: previously logged as a norml message arrival "<="; now
+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 "(=".
 
 
index 2a776b7..587dc65 100644 (file)
@@ -26,6 +26,8 @@ Version 4.88
     the queue to be used for a message.  A $queue_name variable gives
     visibility.
 
+ 6. New expansion operators base32/base32d.
+
 
 Version 4.87
 ------------
index f99aa18..202f7a4 100644 (file)
@@ -6906,8 +6906,8 @@ if (addr_senddsn)
     {
     FILE *f = fdopen(fd, "wb");
     /* header only as required by RFC. only failure DSN needs to honor RET=FULL */
-    int topt = topt_add_return_path | topt_no_body;
     uschar * bound;
+    transport_ctx tctx;
 
     DEBUG(D_deliver)
       debug_printf("sending error message to: %s\n", sender_address);
@@ -6986,7 +6986,10 @@ if (addr_senddsn)
     return_path = sender_address;   /* In case not previously set */
 
     /* Write the original email out */
-    transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0);
+
+    bzero(&tctx, sizeof(tctx));
+    tctx.options = topt_add_return_path | topt_no_body;
+    transport_write_message(fileno(f), &tctx, 0);
     fflush(f);
 
     fprintf(f,"\n--%s--\n", bound);
@@ -7441,8 +7444,18 @@ wording. */
       fflush(f);
       transport_filter_argv = NULL;   /* Just in case */
       return_path = sender_address;   /* In case not previously set */
-      transport_write_message(NULL, fileno(f), topt,
-        0, dsnnotifyhdr, NULL, NULL, NULL, NULL, 0);
+       {                             /* Dummy transport for headers add */
+       transport_ctx * tctx =
+         store_get(sizeof(*tctx) + sizeof(transport_instance));
+       transport_instance * tb = (transport_instance *)(tctx+1);
+
+       bzero(tctx, sizeof(*tctx)+sizeof(*tb));
+       tctx->tblock = tb;
+       tctx->options = topt;
+       tb->add_headers = dsnnotifyhdr;
+
+       transport_write_message(fileno(f), tctx, 0);
+       }
       fflush(f);
 
       /* we never add the final text. close the file */
@@ -7758,7 +7771,9 @@ else if (addr_defer != (address_item *)(+1))
         FILE *wmf = NULL;
         FILE *f = fdopen(fd, "wb");
        uschar * bound;
-        int topt;
+       transport_ctx tctx;
+
+       bzero(&tctx, sizeof(tctx));
 
         if (warn_message_file)
           if (!(wmf = Ufopen(warn_message_file, "rb")))
@@ -7905,11 +7920,12 @@ else if (addr_defer != (address_item *)(+1))
 
         fflush(f);
         /* header only as required by RFC. only failure DSN needs to honor RET=FULL */
-        topt = topt_add_return_path | topt_no_body;
+        tctx.options = topt_add_return_path | topt_no_body;
         transport_filter_argv = NULL;   /* Just in case */
         return_path = sender_address;   /* In case not previously set */
+
         /* Write the original email out */
-        transport_write_message(NULL, fileno(f), topt, 0, NULL, NULL, NULL, NULL, NULL, 0);
+        transport_write_message(fileno(f), &tctx, 0);
         fflush(f);
 
         fprintf(f,"\n--%s--\n", bound);
index 4e20f14..e027a23 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? */
 }
 
 
@@ -95,10 +95,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;
 }
 
@@ -110,6 +116,7 @@ pdkim_signature *sig = NULL;
 int dkim_signers_size = 0;
 int dkim_signers_ptr = 0;
 dkim_signers = NULL;
+int rc;
 
 store_pool = POOL_PERM;
 
@@ -134,8 +141,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)
   {
@@ -148,10 +159,12 @@ for (sig = dkim_signatures; sig; sig = sig->next)
        string_sprintf("d=%s s=%s c=%s/%s a=%s b=%d ",
              sig->domain,
              sig->selector,
-             sig->canon_headers == PDKIM_CANON_SIMPLE ?  "simple" : "relaxed",
-             sig->canon_body == PDKIM_CANON_SIMPLE ?  "simple" : "relaxed",
-             sig->algo == PDKIM_ALGO_RSA_SHA256 ?  "rsa-sha256" : "rsa-sha1",
-             sig->sigdata.len * 8
+             sig->canon_headers == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
+             sig->canon_body == PDKIM_CANON_SIMPLE ? "simple" : "relaxed",
+             sig->algo == PDKIM_ALGO_RSA_SHA256
+             ? "rsa-sha256"
+             : sig->algo == PDKIM_ALGO_RSA_SHA1 ? "rsa-sha1" : "err",
+             (int)sig->sigdata.len > -1 ? sig->sigdata.len * 8 : 0
              ),
 
        sig->identity ? string_sprintf("i=%s ", sig->identity) : US"",
@@ -186,6 +199,16 @@ for (sig = dkim_signatures; sig; sig = sig->next)
                       "syntax error in public key record]");
          break;
 
+        case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR:
+          logmsg = string_append(logmsg, &size, &ptr, 1,
+                       "signature tag missing or invalid]");
+          break;
+
+        case PDKIM_VERIFY_INVALID_DKIM_VERSION:
+          logmsg = string_append(logmsg, &size, &ptr, 1,
+                       "unsupported DKIM version]");
+          break;
+
        default:
          logmsg = string_append(logmsg, &size, &ptr, 1,
                        "unspecified problem]");
@@ -466,8 +489,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. */
@@ -504,8 +526,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 */
@@ -516,8 +537,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)
@@ -538,8 +558,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 */
 
@@ -549,8 +568,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
@@ -572,25 +590,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,
@@ -601,27 +617,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");
@@ -639,11 +647,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 ebbdc55..4909d9f 100644 (file)
@@ -144,9 +144,8 @@ extern uschar *deliver_get_sender_address (uschar *id);
 
 extern BOOL    directory_make(const uschar *, const uschar *, int, BOOL);
 #ifndef DISABLE_DKIM
-extern BOOL    dkim_transport_write_message(address_item *, int, int,
-                   int, uschar *, uschar *, uschar *, uschar *, rewrite_rule *,
-                   int, uschar *, uschar *, uschar *, uschar *, uschar *, uschar *);
+extern BOOL    dkim_transport_write_message(int, transport_ctx *,
+                 struct ob_dkim *);
 #endif
 extern dns_address *dns_address_from_rr(dns_answer *, dns_record *);
 extern int     dns_basic_lookup(dns_answer *, const uschar *, int);
@@ -468,10 +467,10 @@ extern BOOL    transport_set_up_command(const uschar ***, uschar *,
 extern void    transport_update_waiting(host_item *, uschar *);
 extern BOOL    transport_write_block(int, uschar *, int);
 extern BOOL    transport_write_string(int, const char *, ...);
-extern BOOL    transport_headers_send(address_item *, int, uschar *, uschar *,
-                 BOOL (*)(int, uschar *, int, BOOL), BOOL, rewrite_rule *, int);
-extern BOOL    transport_write_message(address_item *, int, int, int, uschar *,
-                 uschar *, uschar *, uschar *, rewrite_rule *, int);
+extern BOOL    transport_headers_send(address_item *, int, transport_instance *,
+                 BOOL (*)(int, uschar *, int, BOOL),
+                BOOL);
+extern BOOL    transport_write_message(int, transport_ctx *, int);
 extern void    tree_add_duplicate(uschar *, address_item *);
 extern void    tree_add_nonrecipient(uschar *);
 extern void    tree_add_unusable(host_item *);
index 29277ba..f468d23 100644 (file)
@@ -115,26 +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";
-    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)";
   }
 }
 
@@ -407,6 +428,10 @@ sig = store_get(sizeof(pdkim_signature));
 memset(sig, 0, sizeof(pdkim_signature));
 sig->bodylength = -1;
 
+/* Set so invalid/missing data error display is accurate */
+sig->algo = -1;
+sig->version = 0;
+
 q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);
 
 for (p = raw_hdr; ; p++)
@@ -476,8 +501,8 @@ for (p = raw_hdr; ; p++)
          case 'v':
              /* We only support version 1, and that is currently the
                 only version there is. */
-           if (Ustrcmp(cur_val, PDKIM_SIGNATURE_VERSION) == 0)
-             sig->version = 1;
+           sig->version =
+             Ustrcmp(cur_val, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
            break;
          case 'a':
            for (i = 0; pdkim_algos[i]; i++)
@@ -542,10 +567,6 @@ NEXT_CHAR:
     *q++ = c;
   }
 
-/* Make sure the most important bits are there. */
-if (!sig->version)
-  return NULL;
-
 *q = '\0';
 /* Chomp raw header. The final newline must not be added to the signature. */
 while (--q > sig->rawsig_no_b_val  && (*q == '\r' || *q == '\n'))
@@ -1475,6 +1496,37 @@ while (sig)
 
     uschar *dns_txt_name, *dns_txt_reply;
 
+    /* Make sure we have all required signature tags */
+    if (!(  sig->domain        && *sig->domain
+        && sig->selector      && *sig->selector
+        && sig->headernames   && *sig->headernames
+        && sig->bodyhash.data
+        && sig->sigdata.data
+        && sig->algo > -1
+        && sig->version
+       ) )
+      {
+      sig->verify_status     = PDKIM_VERIFY_INVALID;
+      sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
+
+      DEBUG(D_acl) debug_printf(
+         " Error in DKIM-Signature header: tags missing or invalid\n"
+         "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+      goto NEXT_VERIFY;
+      }
+
+    /* Make sure sig uses supported DKIM version (only v1) */
+    if (sig->version != 1)
+      {
+      sig->verify_status     = PDKIM_VERIFY_INVALID;
+      sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
+
+      DEBUG(D_acl) debug_printf(
+          " Error in DKIM-Signature header: unsupported DKIM version\n"
+          "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
+      goto NEXT_VERIFY;
+      }
+
     /* Fetch public key for signing domain, from DNS */
 
     dns_txt_name = string_sprintf("%s._domainkey.%s.",
index ba984c1..5d0157e 100644 (file)
 #define PDKIM_VERIFY_FAIL      2
 #define PDKIM_VERIFY_PASS      3
 
-#define PDKIM_VERIFY_FAIL_BODY                  1
-#define PDKIM_VERIFY_FAIL_MESSAGE               2
-#define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE 3
-#define PDKIM_VERIFY_INVALID_BUFFER_SIZE        4
-#define PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD   5
-#define PDKIM_VERIFY_INVALID_PUBKEY_IMPORT      6
+#define PDKIM_VERIFY_FAIL_BODY                    1
+#define PDKIM_VERIFY_FAIL_MESSAGE                 2
+#define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE   3
+#define PDKIM_VERIFY_INVALID_BUFFER_SIZE          4
+#define PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD     5
+#define PDKIM_VERIFY_INVALID_PUBKEY_IMPORT        6
+#define PDKIM_VERIFY_INVALID_SIGNATURE_ERROR      7
+#define PDKIM_VERIFY_INVALID_DKIM_VERSION         8
 
 /* -------------------------------------------------------------------------- */
 /* Some parameter values */
@@ -302,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 1b7b9f7..7648f47 100644 (file)
@@ -1145,7 +1145,7 @@ switch(action)
   case MSG_SHOW_COPY:
   deliver_in_buffer = store_malloc(DELIVER_IN_BUFFER_SIZE);
   deliver_out_buffer = store_malloc(DELIVER_OUT_BUFFER_SIZE);
-  transport_write_message(NULL, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, 0);
+  transport_write_message(1, NULL, 0);
   break;
 
 
index d17cf9b..3215479 100644 (file)
@@ -682,7 +682,8 @@ while ((ch = (receive_getc)()) != EOF)
     case 1:                         /* After written "\n" */
     if (ch == '.') { ch_state = 3; continue; }
     if (ch == '\r') { ch_state = 2; continue; }
-    if (ch != '\n') ch_state = 0; else linelength = -1;
+    if (ch == '\n') { body_linecount++; linelength = -1; }
+    else ch_state = 0;
     break;
 
     case 2:
@@ -3894,7 +3895,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);
       }
     }
@@ -4014,7 +4017,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;
 
index 78f5a80..6666c52 100644 (file)
@@ -218,6 +218,17 @@ typedef struct transport_info {
 } transport_info;
 
 
+/* Structure for information about a delivery-in-progress */
+
+typedef struct transport_context {
+  transport_instance * tblock;
+  struct address_item * addr;
+  uschar       * check_string;
+  uschar       * escape_string;
+  int            options;              /* topt_* */
+} transport_ctx;
+
+
 
 typedef struct {
   uschar *request;
@@ -826,4 +837,14 @@ typedef struct acl_block {
 /* smtp transport calc outbound_ip */
 typedef BOOL (*oicf) (uschar *message_id, void *data);
 
+/* DKIM information for transport */
+struct ob_dkim {
+  uschar *dkim_domain;
+  uschar *dkim_private_key;
+  uschar *dkim_selector;
+  uschar *dkim_canon;
+  uschar *dkim_sign_headers;
+  uschar *dkim_strict;
+} dkim;
+
 /* End of structs.h */
index e1e6dce..8e0a802 100644 (file)
@@ -369,7 +369,7 @@ write_chunk(int fd, uschar *chunk, int len, BOOL use_crlf)
 {
 uschar *start = chunk;
 uschar *end = chunk + len;
-register uschar *ptr;
+uschar *ptr;
 int mlen = DELIVER_OUT_BUFFER_SIZE - nl_escape_length - 2;
 
 /* The assumption is made that the check string will never stretch over move
@@ -408,7 +408,7 @@ possible. */
 
 for (ptr = start; ptr < end; ptr++)
   {
-  register int ch;
+  int ch;
 
   /* Flush the buffer if it has reached the threshold - we want to leave enough
   room for the next uschar, plus a possible extra CR for an LF, plus the escape
@@ -560,8 +560,7 @@ struct aci *ppp;
 /* Do nothing if we have already handled this address. If not, remember it
 so that we don't handle it again. */
 
-for (ppp = *pdlist; ppp != NULL; ppp = ppp->next)
-  { if (p == ppp->ptr) return TRUE; }
+for (ppp = *pdlist; ppp; ppp = ppp->next) if (p == ppp->ptr) return TRUE;
 
 ppp = store_get(sizeof(struct aci));
 ppp->next = *pdlist;
@@ -573,19 +572,17 @@ ppp->ptr = p;
 for (pp = p;; pp = pp->parent)
   {
   address_item *dup;
-  for (dup = addr_duplicate; dup != NULL; dup = dup->next)
-    {
-    if (dup->dupof != pp) continue;   /* Not a dup of our address */
-    if (!write_env_to(dup, pplist, pdlist, first, fd, use_crlf)) return FALSE;
-    }
-  if (pp->parent == NULL) break;
+  for (dup = addr_duplicate; dup; dup = dup->next)
+    if (dup->dupof == pp)   /* a dup of our address */
+      if (!write_env_to(dup, pplist, pdlist, first, fd, use_crlf))
+       return FALSE;
+  if (!pp->parent) break;
   }
 
 /* Check to see if we have already output the progenitor. */
 
-for (ppp = *pplist; ppp != NULL; ppp = ppp->next)
-  { if (pp == ppp->ptr) break; }
-if (ppp != NULL) return TRUE;
+for (ppp = *pplist; ppp; ppp = ppp->next) if (pp == ppp->ptr) break;
+if (ppp) return TRUE;
 
 /* Remember what we have output, and output it. */
 
@@ -619,11 +616,12 @@ Arguments:
 Returns:                TRUE on success; FALSE on failure.
 */
 BOOL
-transport_headers_send(address_item *addr, int fd, uschar *add_headers, uschar *remove_headers,
+transport_headers_send(address_item *addr, int fd, transport_instance * tblock,
   BOOL (*sendfn)(int fd, uschar * s, int len, BOOL use_crlf),
-  BOOL use_crlf, rewrite_rule *rewrite_rules, int rewrite_existflags)
+  BOOL use_crlf)
 {
 header_line *h;
+const uschar *list;
 
 /* Then the message's headers. Don't write any that are flagged as "old";
 that means they were rewritten, or are a record of envelope rewriting, or
@@ -632,13 +630,12 @@ match any entries therein.  It is a colon-sep list; expand the items
 separately and squash any empty ones.
 Then check addr->prop.remove_headers too, provided that addr is not NULL. */
 
-for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
+for (h = header_list; h; h = h->next) if (h->type != htype_old)
   {
   int i;
-  const uschar *list = remove_headers;
-
   BOOL include_header = TRUE;
 
+  list = tblock ? tblock->remove_headers : NULL;
   for (i = 0; i < 2; i++)    /* For remove_headers && addr->prop.remove_headers */
     {
     if (list)
@@ -661,9 +658,9 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
        while (*ss == ' ' || *ss == '\t') ss++;
        if (*ss == ':') break;
        }
-      if (s != NULL) { include_header = FALSE; break; }
+      if (s) { include_header = FALSE; break; }
       }
-    if (addr != NULL) list = addr->prop.remove_headers;
+    if (addr) list = addr->prop.remove_headers;
     }
 
   /* If this header is to be output, try to rewrite it if there are rewriting
@@ -671,12 +668,13 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old)
 
   if (include_header)
     {
-    if (rewrite_rules)
+    if (tblock && tblock->rewrite_rules)
       {
       void *reset_point = store_get(0);
       header_line *hh;
 
-      if ((hh = rewrite_header(h, NULL, NULL, rewrite_rules, rewrite_existflags, FALSE)))
+      if ((hh = rewrite_header(h, NULL, NULL, tblock->rewrite_rules,
+                 tblock->rewrite_existflags, FALSE)))
        {
        if (!sendfn(fd, hh->text, hh->slen, use_crlf)) return FALSE;
        store_reset(reset_point);
@@ -714,8 +712,7 @@ if (addr)
   header_line *hprev = addr->prop.extra_headers;
   header_line *hnext;
   for (i = 0; i < 2; i++)
-    {
-    for (h = hprev, hprev = NULL; h != NULL; h = hnext)
+    for (h = hprev, hprev = NULL; h; h = hnext)
       {
       hnext = h->next;
       h->next = hprev;
@@ -727,7 +724,6 @@ if (addr)
          debug_printf("added header line(s):\n%s---\n", h->text);
        }
       }
-    }
   }
 
 /* If a string containing additional headers exists it is a newline-sep
@@ -737,18 +733,13 @@ up any other headers. An empty string or a forced expansion failure are
 noops. An added header string from a transport may not end with a newline;
 add one if it does not. */
 
-if (add_headers)
+if (tblock && (list = CUS tblock->add_headers))
   {
   int sep = '\n';
   uschar * s;
 
-  while ((s = string_nextinlist(CUSS &add_headers, &sep, NULL, 0)))
-    if (!(s = expand_string(s)))
-      {
-      if (!expand_string_forcedfail)
-       { errno = ERRNO_CHHEADER_FAIL; return FALSE; }
-      }
-    else
+  while ((s = string_nextinlist(&list, &sep, NULL, 0)))
+    if ((s = expand_string(s)))
       {
       int len = Ustrlen(s);
       if (len > 0)
@@ -764,6 +755,8 @@ if (add_headers)
          }
        }
       }
+    else if (!expand_string_forcedfail)
+      { errno = ERRNO_CHHEADER_FAIL; return FALSE; }
   }
 
 /* Separate headers from body with a blank line */
@@ -801,30 +794,32 @@ can include timeouts for certain transports, which are requested by setting
 transport_write_timeout non-zero.
 
 Arguments:
-  addr                  (chain of) addresses (for extra headers), or NULL;
-                          only the first address is used
   fd                    file descriptor to write the message to
-  options               bit-wise options:
-    add_return_path       if TRUE, add a "return-path" header
-    add_envelope_to       if TRUE, add a "envelope-to" header
-    add_delivery_date     if TRUE, add a "delivery-date" header
-    use_crlf              if TRUE, turn NL into CR LF
-    end_dot               if TRUE, send a terminating "." line at the end
-    no_headers            if TRUE, omit the headers
-    no_body               if TRUE, omit the body
-  size_limit            if > 0, this is a limit to the size of message written;
-                          it is used when returning messages to their senders,
-                          and is approximate rather than exact, owing to chunk
-                          buffering
-  add_headers           a string containing one or more headers to add; it is
-                          expanded, and must be in correct RFC 822 format as
-                          it is transmitted verbatim; NULL => no additions,
-                          and so does empty string or forced expansion fail
-  remove_headers        a colon-separated list of headers to remove, or NULL
-  check_string          a string to check for at the start of lines, or NULL
-  escape_string         a string to insert in front of any check string
-  rewrite_rules         chain of header rewriting rules
-  rewrite_existflags    flags for the rewriting rules
+  tctx
+    addr                (chain of) addresses (for extra headers), or NULL;
+                          only the first address is used
+    tblock             optional transport instance block (NULL signifies NULL/0):
+      add_headers           a string containing one or more headers to add; it is
+                            expanded, and must be in correct RFC 822 format as
+                            it is transmitted verbatim; NULL => no additions,
+                            and so does empty string or forced expansion fail
+      remove_headers        a colon-separated list of headers to remove, or NULL
+      rewrite_rules         chain of header rewriting rules
+      rewrite_existflags    flags for the rewriting rules
+    options               bit-wise options:
+      add_return_path       if TRUE, add a "return-path" header
+      add_envelope_to       if TRUE, add a "envelope-to" header
+      add_delivery_date     if TRUE, add a "delivery-date" header
+      use_crlf              if TRUE, turn NL into CR LF
+      end_dot               if TRUE, send a terminating "." line at the end
+      no_headers            if TRUE, omit the headers
+      no_body               if TRUE, omit the body
+    size_limit            if > 0, this is a limit to the size of message written;
+                            it is used when returning messages to their senders,
+                            and is approximate rather than exact, owing to chunk
+                            buffering
+    check_string          a string to check for at the start of lines, or NULL
+    escape_string         a string to insert in front of any check string
 
 Returns:                TRUE on success; FALSE (with errno) on failure.
                         In addition, the global variable transport_count
@@ -832,13 +827,11 @@ Returns:                TRUE on success; FALSE (with errno) on failure.
 */
 
 static BOOL
-internal_transport_write_message(address_item *addr, int fd, int options,
-  int size_limit, uschar *add_headers, uschar *remove_headers, uschar *check_string,
-  uschar *escape_string, rewrite_rule *rewrite_rules, int rewrite_existflags)
+internal_transport_write_message(int fd, transport_ctx * tctx, int size_limit)
 {
 int written = 0;
 int len;
-BOOL use_crlf  = (options & topt_use_crlf)  != 0;
+BOOL use_crlf = (tctx->options & topt_use_crlf) != 0;
 
 /* Initialize pointer in output buffer. */
 
@@ -847,39 +840,41 @@ chunk_ptr = deliver_out_buffer;
 /* Set up the data for start-of-line data checking and escaping */
 
 nl_partial_match = -1;
-if (check_string != NULL && escape_string != NULL)
+if (tctx->check_string && tctx->escape_string)
   {
-  nl_check = check_string;
+  nl_check = tctx->check_string;
   nl_check_length = Ustrlen(nl_check);
-  nl_escape = escape_string;
+  nl_escape = tctx->escape_string;
   nl_escape_length = Ustrlen(nl_escape);
   }
-else nl_check_length = nl_escape_length = 0;
+else
+  nl_check_length = nl_escape_length = 0;
 
 /* Whether the escaping mechanism is applied to headers or not is controlled by
 an option (set for SMTP, not otherwise). Negate the length if not wanted till
 after the headers. */
 
-if ((options & topt_escape_headers) == 0) nl_check_length = -nl_check_length;
+if (!(tctx->options & topt_escape_headers))
+  nl_check_length = -nl_check_length;
 
 /* Write the headers if required, including any that have to be added. If there
 are header rewriting rules, apply them. */
 
-if ((options & topt_no_headers) == 0)
+if (!(tctx->options & topt_no_headers))
   {
   /* Add return-path: if requested. */
 
-  if ((options & topt_add_return_path) != 0)
+  if (tctx->options & topt_add_return_path)
     {
     uschar buffer[ADDRESS_MAXLENGTH + 20];
-    sprintf(CS buffer, "Return-path: <%.*s>\n", ADDRESS_MAXLENGTH,
+    int n = sprintf(CS buffer, "Return-path: <%.*s>\n", ADDRESS_MAXLENGTH,
       return_path);
-    if (!write_chunk(fd, buffer, Ustrlen(buffer), use_crlf)) return FALSE;
+    if (!write_chunk(fd, buffer, n, use_crlf)) return FALSE;
     }
 
   /* Add envelope-to: if requested */
 
-  if ((options & topt_add_envelope_to) != 0)
+  if (tctx->options & topt_add_envelope_to)
     {
     BOOL first = TRUE;
     address_item *p;
@@ -893,10 +888,9 @@ if ((options & topt_no_headers) == 0)
     anchors for lists of addresses already handled; they have to be defined at
     this level becuase write_env_to() calls itself recursively. */
 
-    for (p = addr; p != NULL; p = p->next)
-      {
-      if (!write_env_to(p, &plist, &dlist, &first, fd, use_crlf)) return FALSE;
-      }
+    for (p = tctx->addr; p; p = p->next)
+      if (!write_env_to(p, &plist, &dlist, &first, fd, use_crlf))
+       return FALSE;
 
     /* Add a final newline and reset the store used for tracking duplicates */
 
@@ -906,11 +900,11 @@ if ((options & topt_no_headers) == 0)
 
   /* Add delivery-date: if requested. */
 
-  if ((options & topt_add_delivery_date) != 0)
+  if (tctx->options & topt_add_delivery_date)
     {
     uschar buffer[100];
-    sprintf(CS buffer, "Delivery-date: %s\n", tod_stamp(tod_full));
-    if (!write_chunk(fd, buffer, Ustrlen(buffer), use_crlf)) return FALSE;
+    int n = sprintf(CS buffer, "Delivery-date: %s\n", tod_stamp(tod_full));
+    if (!write_chunk(fd, buffer, n, use_crlf)) return FALSE;
     }
 
   /* Then the message's headers. Don't write any that are flagged as "old";
@@ -918,8 +912,8 @@ if ((options & topt_no_headers) == 0)
   were removed (e.g. Bcc). If remove_headers is not null, skip any headers that
   match any entries therein. Then check addr->prop.remove_headers too, provided that
   addr is not NULL. */
-  if (!transport_headers_send(addr, fd, add_headers, remove_headers, &write_chunk,
-       use_crlf, rewrite_rules, rewrite_existflags))
+
+  if (!transport_headers_send(tctx->addr, fd, tctx->tblock, &write_chunk, use_crlf))
     return FALSE;
   }
 
@@ -929,7 +923,7 @@ negative in cases where it isn't to apply to the headers). Then ensure the body
 is positioned at the start of its file (following the message id), then write
 it, applying the size limit if required. */
 
-if ((options & topt_no_body) == 0)
+if (!(tctx->options & topt_no_body))
   {
   nl_check_length = abs(nl_check_length);
   nl_partial_match = 0;
@@ -961,7 +955,7 @@ nl_check_length = nl_escape_length = 0;
 
 /* If requested, add a terminating "." line (SMTP output). */
 
-if ((options & topt_end_dot) != 0 && !write_chunk(fd, US".\n", 2, use_crlf))
+if (tctx->options & topt_end_dot && !write_chunk(fd, US".\n", 2, use_crlf))
   return FALSE;
 
 /* Write out any remaining data in the buffer before returning. */
@@ -986,46 +980,29 @@ return (len = chunk_ptr - deliver_out_buffer) <= 0 ||
    signing the file, send the signed message down the original fd (or TLS fd).
 
 Arguments:
-  as for internal_transport_write_message() above, with additional arguments:
-   uschar *dkim_private_key  DKIM: The private key to use (filename or
-                                   plain data)
-   uschar *dkim_domain       DKIM: The domain to use
-   uschar *dkim_selector     DKIM: The selector to use.
-   uschar *dkim_canon        DKIM: The canonalization scheme to use,
-                                   "simple" or "relaxed"
-   uschar *dkim_strict       DKIM: What to do if signing fails:
-                                 1/true  => throw error
-                                 0/false => send anyway
-   uschar *dkim_sign_headers DKIM: List of headers that should be included
-                                   in signature generation
+  as for internal_transport_write_message() above, with additional arguments
+  for DKIM.
 
 Returns:       TRUE on success; FALSE (with errno) for any failure
 */
 
 BOOL
-dkim_transport_write_message(address_item *addr, int fd, int options,
-  int size_limit, uschar *add_headers, uschar *remove_headers,
-  uschar *check_string, uschar *escape_string, rewrite_rule *rewrite_rules,
-  int rewrite_existflags, uschar *dkim_private_key, uschar *dkim_domain,
-  uschar *dkim_selector, uschar *dkim_canon, uschar *dkim_strict, uschar *dkim_sign_headers
-  )
+dkim_transport_write_message(int out_fd, transport_ctx * tctx,
+  struct ob_dkim * dkim)
 {
 int dkim_fd;
 int save_errno = 0;
 BOOL rc;
 uschar * dkim_spool_name;
-char sbuf[2048];
 int sread = 0;
 int wwritten = 0;
 uschar *dkim_signature = NULL;
+off_t k_file_size;
 
 /* If we can't sign, just call the original function. */
 
-if (!(dkim_private_key && dkim_domain && dkim_selector))
-  return transport_write_message(addr, fd, options,
-           size_limit, add_headers, remove_headers,
-           check_string, escape_string, rewrite_rules,
-           rewrite_existflags);
+if (!(dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector))
+  return transport_write_message(out_fd, tctx, 0);
 
 dkim_spool_name = spool_fname(US"input", message_subdir, message_id,
                    string_sprintf("-%d-K", (int)getpid()));
@@ -1038,12 +1015,9 @@ if ((dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE)) < 0)
   goto CLEANUP;
   }
 
-/* Call original function to write the -K file */
+/* Call original function to write the -K file; does the CRLF expansion */
 
-rc = transport_write_message(addr, dkim_fd, options,
-  size_limit, add_headers, remove_headers,
-  check_string, escape_string, rewrite_rules,
-  rewrite_existflags);
+rc = transport_write_message(dkim_fd, tctx, 0);
 
 /* Save error state. We must clean up before returning. */
 if (!rc)
@@ -1052,24 +1026,24 @@ if (!rc)
   goto CLEANUP;
   }
 
-if (dkim_private_key && dkim_domain && dkim_selector)
+if (dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector)
   {
   /* Rewind file and feed it to the goats^W DKIM lib */
   lseek(dkim_fd, 0, SEEK_SET);
   dkim_signature = dkim_exim_sign(dkim_fd,
-                                 dkim_private_key,
-                                 dkim_domain,
-                                 dkim_selector,
-                                 dkim_canon,
-                                 dkim_sign_headers);
+                                 dkim->dkim_private_key,
+                                 dkim->dkim_domain,
+                                 dkim->dkim_selector,
+                                 dkim->dkim_canon,
+                                 dkim->dkim_sign_headers);
   if (!dkim_signature)
     {
-    if (dkim_strict)
+    if (dkim->dkim_strict)
       {
-      uschar *dkim_strict_result = expand_string(dkim_strict);
+      uschar *dkim_strict_result = expand_string(dkim->dkim_strict);
       if (dkim_strict_result)
-       if ( (strcmpic(dkim_strict,US"1") == 0) ||
-            (strcmpic(dkim_strict,US"true") == 0) )
+       if ( (strcmpic(dkim->dkim_strict,US"1") == 0) ||
+            (strcmpic(dkim->dkim_strict,US"true") == 0) )
          {
          /* Set errno to something halfway meaningful */
          save_errno = EACCES;
@@ -1080,20 +1054,21 @@ if (dkim_private_key && dkim_domain && dkim_selector)
          }
       }
     }
-  else
+
+  if (dkim_signature)
     {
     int siglen = Ustrlen(dkim_signature);
     while(siglen > 0)
       {
 #ifdef SUPPORT_TLS
-      wwritten = tls_out.active == fd
-       ? tls_write(FALSE, dkim_signature, siglen)
-       : write(fd, dkim_signature, siglen);
+       wwritten = tls_out.active == out_fd
+         ? tls_write(FALSE, dkim_signature, siglen)
+         : write(out_fd, dkim_signature, siglen);
 #else
-      wwritten = write(fd, dkim_signature, siglen);
+       wwritten = write(out_fd, dkim_signature, siglen);
 #endif
       if (wwritten == -1)
-        {
+       {
        /* error, bail out */
        save_errno = errno;
        rc = FALSE;
@@ -1110,17 +1085,18 @@ if (dkim_private_key && dkim_domain && dkim_selector)
    to the socket. However only if we don't use TLS,
    as then there's another layer of indirection
    before the data finally hits the socket. */
-if (tls_out.active != fd)
+if (tls_out.active != out_fd)
   {
-  off_t size = lseek(dkim_fd, 0, SEEK_END); /* Fetch file size */
   ssize_t copied = 0;
   off_t offset = 0;
 
+  k_file_size = lseek(dkim_fd, 0, SEEK_END); /* Fetch file size */
+
   /* Rewind file */
   lseek(dkim_fd, 0, SEEK_SET);
 
-  while(copied >= 0 && offset < size)
-    copied = sendfile(fd, dkim_fd, &offset, size - offset);
+  while(copied >= 0 && offset < k_file_size)
+    copied = sendfile(out_fd, dkim_fd, &offset, k_file_size - offset);
   if (copied < 0)
     {
     save_errno = errno;
@@ -1136,19 +1112,19 @@ else
   lseek(dkim_fd, 0, SEEK_SET);
 
   /* Send file down the original fd */
-  while((sread = read(dkim_fd, sbuf, 2048)) > 0)
+  while((sread = read(dkim_fd, deliver_out_buffer, DELIVER_OUT_BUFFER_SIZE)) >0)
     {
-    char *p = sbuf;
+    char *p = deliver_out_buffer;
     /* write the chunk */
 
     while (sread)
       {
 #ifdef SUPPORT_TLS
-      wwritten = tls_out.active == fd
+      wwritten = tls_out.active == out_fd
        ? tls_write(FALSE, US p, sread)
-       : write(fd, p, sread);
+       : write(out_fd, p, sread);
 #else
-      wwritten = write(fd, p, sread);
+      wwritten = write(out_fd, p, sread);
 #endif
       if (wwritten == -1)
        {
@@ -1191,6 +1167,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
@@ -1198,16 +1175,16 @@ Returns:       TRUE on success; FALSE (with errno) for any failure
 */
 
 BOOL
-transport_write_message(address_item *addr, int fd, int options,
-  int size_limit, uschar *add_headers, uschar *remove_headers,
-  uschar *check_string, uschar *escape_string, rewrite_rule *rewrite_rules,
-  int rewrite_existflags)
+transport_write_message(int fd, transport_ctx * tctx, int size_limit)
 {
 BOOL use_crlf;
 BOOL last_filter_was_NL = TRUE;
 int rc, len, yield, fd_read, fd_write, save_errno;
 int pfd[2] = {-1, -1};
 pid_t filter_pid, write_pid;
+static transport_ctx dummy_tctx = { NULL, NULL, NULL, NULL, 0 };
+
+if (!tctx) tctx = &dummy_tctx;
 
 transport_filter_timed_out = FALSE;
 
@@ -1218,22 +1195,20 @@ if (  !transport_filter_argv
    || !*transport_filter_argv
    || !**transport_filter_argv
    )
-  return internal_transport_write_message(addr, fd, options, size_limit,
-    add_headers, remove_headers, check_string, escape_string,
-    rewrite_rules, rewrite_existflags);
+  return internal_transport_write_message(fd, tctx, size_limit);
 
 /* Otherwise the message must be written to a filter process and read back
 before being written to the incoming fd. First set up the special processing to
 be done during the copying. */
 
-use_crlf  = (options & topt_use_crlf) != 0;
+use_crlf = (tctx->options & topt_use_crlf) != 0;
 nl_partial_match = -1;
 
-if (check_string != NULL && escape_string != NULL)
+if (tctx->check_string && tctx->escape_string)
   {
-  nl_check = check_string;
+  nl_check = tctx->check_string;
   nl_check_length = Ustrlen(nl_check);
-  nl_escape = escape_string;
+  nl_escape = tctx->escape_string;
   nl_escape_length = Ustrlen(nl_escape);
   }
 else nl_check_length = nl_escape_length = 0;
@@ -1257,7 +1232,7 @@ filter_pid = child_open(USS transport_filter_argv, NULL, 077,
 if (filter_pid < 0) goto TIDY_UP;      /* errno set */
 
 DEBUG(D_transport)
-  debug_printf("process %d running as transport filter: write=%d read=%d\n",
+  debug_printf("process %d running as transport filter: fd_write=%d fd_read=%d\n",
     (int)filter_pid, fd_write, fd_read);
 
 /* Fork subprocess to write the message to the filter, and return the result
@@ -1271,16 +1246,18 @@ if ((write_pid = fork()) == 0)
   (void)close(fd_read);
   (void)close(pfd[pipe_read]);
   nl_check_length = nl_escape_length = 0;
-  rc = internal_transport_write_message(addr, fd_write,
-    (options & ~(topt_use_crlf | topt_end_dot)),
-    size_limit, add_headers, remove_headers, NULL, NULL,
-    rewrite_rules, rewrite_existflags);
+
+  tctx->check_string = tctx->escape_string = NULL;
+  tctx->options &= ~(topt_use_crlf | topt_end_dot);
+
+  rc = internal_transport_write_message(fd_write, tctx, size_limit);
+
   save_errno = errno;
   if (  write(pfd[pipe_write], (void *)&rc, sizeof(BOOL))
         != sizeof(BOOL)
      || write(pfd[pipe_write], (void *)&save_errno, sizeof(int))
         != sizeof(int)
-     || write(pfd[pipe_write], (void *)&(addr->more_errno), sizeof(int))
+     || write(pfd[pipe_write], (void *)&tctx->addr->more_errno, sizeof(int))
         != sizeof(int)
      )
     rc = FALSE;        /* compiler quietening */
@@ -1377,7 +1354,7 @@ if (filter_pid > 0 && (rc = child_close(filter_pid, 30)) != 0 && yield)
   {
   yield = FALSE;
   save_errno = ERRNO_FILTER_FAIL;
-  addr->more_errno = rc;
+  tctx->addr->more_errno = rc;
   DEBUG(D_transport) debug_printf("filter process returned %d\n", rc);
   }
 
@@ -1398,7 +1375,7 @@ if (write_pid > 0)
       if (!ok)
         {
         dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int));
-        dummy = read(pfd[pipe_read], (void *)&(addr->more_errno), sizeof(int));
+        dummy = read(pfd[pipe_read], (void *)&(tctx->addr->more_errno), sizeof(int));
         yield = FALSE;
         }
       }
@@ -1406,7 +1383,7 @@ if (write_pid > 0)
       {
       yield = FALSE;
       save_errno = ERRNO_FILTER_FAIL;
-      addr->more_errno = rc;
+      tctx->addr->more_errno = rc;
       DEBUG(D_transport) debug_printf("writing process returned %d\n", rc);
       }
     }
@@ -1420,28 +1397,27 @@ filter was not NL, insert a NL to make the SMTP protocol work. */
 if (yield)
   {
   nl_check_length = nl_escape_length = 0;
-  if ((options & topt_end_dot) != 0 && (last_filter_was_NL?
-        !write_chunk(fd, US".\n", 2, use_crlf) :
-        !write_chunk(fd, US"\n.\n", 3, use_crlf)))
-    {
+  if (  tctx->options & topt_end_dot
+     && ( last_filter_was_NL
+        ? !write_chunk(fd, US".\n", 2, use_crlf)
+       : !write_chunk(fd, US"\n.\n", 3, use_crlf)
+     )  )
     yield = FALSE;
-    }
 
   /* Write out any remaining data in the buffer. */
 
   else
-    {
-    yield = (len = chunk_ptr - deliver_out_buffer) <= 0 ||
-      transport_write_block(fd, deliver_out_buffer, len);
-    }
+    yield = (len = chunk_ptr - deliver_out_buffer) <= 0
+         || transport_write_block(fd, deliver_out_buffer, len);
   }
-else errno = save_errno;      /* From some earlier error */
+else
+  errno = save_errno;      /* From some earlier error */
 
 DEBUG(D_transport)
   {
   debug_printf("end of filtering transport writing: yield=%d\n", yield);
   if (!yield)
-    debug_printf("errno=%d more_errno=%d\n", errno, addr->more_errno);
+    debug_printf("errno=%d more_errno=%d\n", errno, tctx->addr->more_errno);
   }
 
 return yield;
index 5dc4ee9..c9d1505 100644 (file)
@@ -2874,9 +2874,14 @@ at initialization time. */
 
 if (yield == OK)
   {
-  if (!transport_write_message(addr, fd, ob->options, 0, tblock->add_headers,
-      tblock->remove_headers, ob->check_string, ob->escape_string,
-      tblock->rewrite_rules, tblock->rewrite_existflags))
+  transport_ctx tctx = {
+    tblock,
+    addr,
+    ob->check_string,
+    ob->escape_string,
+    ob->options
+  };
+  if (!transport_write_message(fd, &tctx, 0))
     yield = DEFER;
   }
 
index 54f9ef4..36a68b9 100644 (file)
@@ -691,6 +691,17 @@ if (return_message)
     US"------ This is a copy of the body of the message, without the headers.\n"
     :
     US"------ This is a copy of the message, including all the headers.\n";
+  transport_ctx tctx = {
+    tblock,
+    addr,
+    NULL,
+    NULL,
+    (tblock->body_only ? topt_no_headers : 0) |
+    (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)
+  };
 
   if (bounce_return_size_limit > 0 && !tblock->headers_only)
     {
@@ -710,14 +721,7 @@ if (return_message)
 
   fflush(f);
   transport_count = 0;
-  transport_write_message(addr, fileno(f),
-    (tblock->body_only? topt_no_headers : 0) |
-    (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),
-    bounce_return_size_limit, tblock->add_headers, tblock->remove_headers,
-    NULL, NULL, tblock->rewrite_rules, tblock->rewrite_existflags);
+  transport_write_message(fileno(f), &tctx, bounce_return_size_limit);
   }
 
 /* End the message and wait for the child process to end; no timeout. */
index bca5978..9624ece 100644 (file)
@@ -609,6 +609,13 @@ for (addr = addrlist; addr != NULL; addr = addr->next)
 if (send_data)
   {
   BOOL ok;
+  transport_ctx tctx = {
+    tblock,
+    addrlist,
+    US".",
+    US"..",
+    ob->options
+  };
 
   if (!lmtp_write_command(fd_in, "DATA\r\n")) goto WRITE_FAILED;
   if (!lmtp_read_response(out, buffer, sizeof(buffer), '3', timeout))
@@ -628,9 +635,7 @@ if (send_data)
     debug_printf("  LMTP>> writing message and terminating \".\"\n");
 
   transport_count = 0;
-  ok = transport_write_message(addrlist, fd_in, ob->options, 0,
-        tblock->add_headers, tblock->remove_headers, US".", US"..",
-        tblock->rewrite_rules, tblock->rewrite_existflags);
+  ok = transport_write_message(fd_in, &tctx, 0);
 
   /* Failure can either be some kind of I/O disaster (including timeout),
   or the failure of a transport filter or the expansion of added headers. */
index db522e5..e3d0197 100644 (file)
@@ -555,6 +555,13 @@ uschar *envp[50];
 const uschar *envlist = ob->environment;
 uschar *cmd, *ss;
 uschar *eol = (ob->use_crlf)? US"\r\n" : US"\n";
+transport_ctx tctx = {
+  tblock,
+  addr,
+  ob->check_string,
+  ob->escape_string,
+  ob->options /* set at initialization time */
+};
 
 DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);
 
@@ -842,23 +849,19 @@ if (ob->use_bsmtp)
   if (!transport_write_string(fd_in, "MAIL FROM:<%s>%s", return_path, eol))
     goto END_WRITE;
 
-  for (a = addr; a != NULL; a = a->next)
-    {
+  for (a = addr; a; a = a->next)
     if (!transport_write_string(fd_in,
         "RCPT TO:<%s>%s",
         transport_rcpt_address(a, tblock->rcpt_include_affixes),
         eol))
       goto END_WRITE;
-    }
 
   if (!transport_write_string(fd_in, "DATA%s", eol)) goto END_WRITE;
   }
 
-/* Now the actual message - the options were set at initialization time */
+/* Now the actual message */
 
-if (!transport_write_message(addr, fd_in, ob->options, 0, tblock->add_headers,
-  tblock->remove_headers, ob->check_string, ob->escape_string,
-  tblock->rewrite_rules, tblock->rewrite_existflags))
+if (!transport_write_message(fd_in, &tctx, 0))
     goto END_WRITE;
 
 /* Now any configured suffix */
index 3d12988..bbfef06 100644 (file)
@@ -44,17 +44,17 @@ optionlist smtp_transport_options[] = {
       (void *)offsetof(smtp_transport_options_block, delay_after_cutoff) },
 #ifndef DISABLE_DKIM
   { "dkim_canon", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, dkim_canon) },
+      (void *)offsetof(smtp_transport_options_block, dkim.dkim_canon) },
   { "dkim_domain", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, dkim_domain) },
+      (void *)offsetof(smtp_transport_options_block, dkim.dkim_domain) },
   { "dkim_private_key", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, dkim_private_key) },
+      (void *)offsetof(smtp_transport_options_block, dkim.dkim_private_key) },
   { "dkim_selector", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, dkim_selector) },
+      (void *)offsetof(smtp_transport_options_block, dkim.dkim_selector) },
   { "dkim_sign_headers", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, dkim_sign_headers) },
+      (void *)offsetof(smtp_transport_options_block, dkim.dkim_sign_headers) },
   { "dkim_strict", opt_stringptr,
-      (void *)offsetof(smtp_transport_options_block, dkim_strict) },
+      (void *)offsetof(smtp_transport_options_block, dkim.dkim_strict) },
 #endif
   { "dns_qualify_single",   opt_bool,
       (void *)offsetof(smtp_transport_options_block, dns_qualify_single) },
@@ -256,12 +256,12 @@ smtp_transport_options_block smtp_transport_option_defaults = {
   US"*"                /* tls_verify_cert_hostnames */
 #endif
 #ifndef DISABLE_DKIM
- ,NULL,                /* dkim_canon */
-  NULL,                /* dkim_domain */
-  NULL,                /* dkim_private_key */
-  NULL,                /* dkim_selector */
-  NULL,                /* dkim_sign_headers */
-  NULL                 /* dkim_strict */
+ , {NULL,              /* dkim_canon */
+    NULL,              /* dkim_domain */
+    NULL,              /* dkim_private_key */
+    NULL,              /* dkim_selector */
+    NULL,              /* dkim_sign_headers */
+    NULL}              /* dkim_strict */
 #endif
 };
 
@@ -279,6 +279,7 @@ static uschar *rf_names[] = { US"NEVER", US"SUCCESS", US"FAILURE", US"DELAY" };
 static uschar *smtp_command;   /* Points to last cmd for error messages */
 static uschar *mail_command;   /* Points to MAIL cmd for error messages */
 static BOOL    update_waiting; /* TRUE to update the "wait" database */
+static BOOL    pipelining_active; /* current transaction is in pipe mode */
 
 
 /*************************************************
@@ -507,13 +508,7 @@ static BOOL
 check_response(host_item *host, int *errno_value, int more_errno,
   uschar *buffer, int *yield, uschar **message, BOOL *pass_message)
 {
-uschar *pl = US"";
-
-if (smtp_use_pipelining &&
-    (Ustrcmp(smtp_command, "MAIL") == 0 ||
-     Ustrcmp(smtp_command, "RCPT") == 0 ||
-     Ustrcmp(smtp_command, "DATA") == 0))
-  pl = US"pipelined ";
+uschar * pl = pipelining_active ? US"pipelined " : US"";
 
 *yield = '4';    /* Default setting is to give a temporary error */
 
@@ -1222,7 +1217,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:
@@ -1315,40 +1311,40 @@ uschar
 ehlo_response(uschar * buf, size_t bsize, uschar checks)
 {
 #ifdef SUPPORT_TLS
-if (checks & PEER_OFFERED_TLS)
-  if (pcre_exec(regex_STARTTLS, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_TLS;
+if (  checks & PEER_OFFERED_TLS
+   && pcre_exec(regex_STARTTLS, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_TLS;
 #endif
 
-  if (  checks & PEER_OFFERED_IGNQ
-     && pcre_exec(regex_IGNOREQUOTA, NULL, CS buf, bsize, 0,
-                 PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_IGNQ;
+if (  checks & PEER_OFFERED_IGNQ
+   && pcre_exec(regex_IGNOREQUOTA, NULL, CS buf, bsize, 0,
+               PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_IGNQ;
 
 #ifndef DISABLE_PRDR
-  if (  checks & PEER_OFFERED_PRDR
-     && pcre_exec(regex_PRDR, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_PRDR;
+if (  checks & PEER_OFFERED_PRDR
+   && pcre_exec(regex_PRDR, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_PRDR;
 #endif
 
 #ifdef SUPPORT_I18N
-  if (  checks & PEER_OFFERED_UTF8
-     && pcre_exec(regex_UTF8, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_UTF8;
+if (  checks & PEER_OFFERED_UTF8
+   && pcre_exec(regex_UTF8, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_UTF8;
 #endif
 
-  if (  checks & PEER_OFFERED_DSN
-     && pcre_exec(regex_DSN, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_DSN;
+if (  checks & PEER_OFFERED_DSN
+   && pcre_exec(regex_DSN, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_DSN;
 
-  if (  checks & PEER_OFFERED_PIPE
-     && pcre_exec(regex_PIPELINING, NULL, CS buf, bsize, 0,
-                 PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_PIPE;
+if (  checks & PEER_OFFERED_PIPE
+   && pcre_exec(regex_PIPELINING, NULL, CS buf, bsize, 0,
+               PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_PIPE;
 
-  if (  checks & PEER_OFFERED_SIZE
-     && pcre_exec(regex_SIZE, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
-    checks &= ~PEER_OFFERED_SIZE;
+if (  checks & PEER_OFFERED_SIZE
+   && pcre_exec(regex_SIZE, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
+  checks &= ~PEER_OFFERED_SIZE;
 
 return checks;
 }
@@ -1709,13 +1705,7 @@ goto SEND_QUIT;
 
   if (esmtp || lmtp)
     peer_offered = ehlo_response(buffer, Ustrlen(buffer),
-      PEER_OFFERED_TLS
-      | 0      /* IGNQ checked later */
-      | 0      /* PRDR checked later */
-      | 0      /* UTF8 checked later */
-      | 0      /* DSN  checked later */
-      | 0      /* PIPE checked later */
-      | 0      /* SIZE checked later */
+      PEER_OFFERED_TLS /* others checked later */
       );
 
   /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
@@ -1977,6 +1967,7 @@ if (continue_hostname == NULL
     case FAIL:         goto RESPONSE_FAILED;
     }
   }
+pipelining_active = smtp_use_pipelining;
 
 /* The setting up of the SMTP call is now complete. Any subsequent errors are
 message-specific. */
@@ -2099,13 +2090,11 @@ if (smtp_use_dsn && !dsn_all_lasthop)
   {
   if (dsn_ret == dsn_ret_hdrs)
     {
-    Ustrcpy(p, " RET=HDRS");
-    while (*p) p++;
+    Ustrcpy(p, " RET=HDRS"); p += 9;
     }
   else if (dsn_ret == dsn_ret_full)
     {
-    Ustrcpy(p, " RET=FULL");
-    while (*p) p++;
+    Ustrcpy(p, " RET=FULL"); p += 9;
     }
   if (dsn_envid != NULL)
     {
@@ -2198,7 +2187,7 @@ the PENDING_DEFER status, because only one attempt is ever made, and we know
 that max_rcpt will be large, so all addresses will be done at once. */
 
 for (addr = first_addr;
-     address_count < max_rcpt && addr != NULL;
+     addr  &&  address_count < max_rcpt;
      addr = addr->next)
   {
   int count;
@@ -2210,14 +2199,14 @@ for (addr = first_addr;
   if (addr->transport_return != PENDING_DEFER) continue;
 
   address_count++;
-  no_flush = smtp_use_pipelining && (!mua_wrapper || addr->next != NULL);
+  no_flush = smtp_use_pipelining && (!mua_wrapper || addr->next);
 
   /* Add any DSN flags to the rcpt command and add to the sent string */
 
   p = buffer;
   *p = 0;
 
-  if (smtp_use_dsn && (addr->dsn_flags & rf_dsnlasthop) != 1)
+  if (smtp_use_dsn && !(addr->dsn_flags & rf_dsnlasthop))
     {
     if ((addr->dsn_flags & rf_dsnflags) != 0)
       {
@@ -2235,7 +2224,7 @@ for (addr = first_addr;
           }
       }
 
-    if (addr->dsn_orcpt != NULL)
+    if (addr->dsn_orcpt)
       {
       string_format(p, sizeof(buffer) - (p-buffer), " ORCPT=%s",
         addr->dsn_orcpt);
@@ -2334,6 +2323,7 @@ if (ok || (smtp_use_pipelining && !mua_wrapper))
     case -1: goto END_OFF;               /* Timeout on RCPT */
     default: goto RESPONSE_FAILED;       /* I/O error, or any MAIL/DATA error */
     }
+  pipelining_active = FALSE;
   }
 
 /* Save the first address of the next batch. */
@@ -2347,8 +2337,22 @@ for handling the SMTP dot-handling protocol, flagging to apply to headers as
 well as body. Set the appropriate timeout value to be used for each chunk.
 (Haven't been able to make it work using select() for writing yet.) */
 
-if (!ok) ok = TRUE; else
+if (!ok)
+  ok = TRUE;
+else
   {
+  transport_ctx tctx = {
+    tblock,
+    addrlist,
+    US".", US"..",    /* Escaping strings */
+    topt_use_crlf | topt_end_dot | topt_escape_headers
+    | (tblock->body_only       ? topt_no_headers : 0)
+    | (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)
+  };
+
   sigalrm_seen = FALSE;
   transport_write_timeout = ob->data_timeout;
   smtp_command = US"sending data block";   /* For error messages */
@@ -2357,32 +2361,9 @@ if (!ok) ok = TRUE; else
   transport_count = 0;
 
 #ifndef DISABLE_DKIM
-  ok = dkim_transport_write_message(addrlist, inblock.sock,
-    topt_use_crlf | topt_end_dot | topt_escape_headers |
-      (tblock->body_only? topt_no_headers : 0) |
-      (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),
-    0,            /* No size limit */
-    tblock->add_headers, tblock->remove_headers,
-    US".", US"..",    /* Escaping strings */
-    tblock->rewrite_rules, tblock->rewrite_existflags,
-    ob->dkim_private_key, ob->dkim_domain, ob->dkim_selector,
-    ob->dkim_canon, ob->dkim_strict, ob->dkim_sign_headers
-    );
+  ok = dkim_transport_write_message(inblock.sock, &tctx, &ob->dkim);
 #else
-  ok = transport_write_message(addrlist, inblock.sock,
-    topt_use_crlf | topt_end_dot | topt_escape_headers |
-      (tblock->body_only? topt_no_headers : 0) |
-      (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),
-    0,            /* No size limit */
-    tblock->add_headers, tblock->remove_headers,
-    US".", US"..",    /* Escaping strings */
-    tblock->rewrite_rules, tblock->rewrite_existflags);
+  ok = transport_write_message(inblock.sock, &tctx, 0);
 #endif
 
   /* transport_write_message() uses write() because it is called from other
@@ -2464,7 +2445,9 @@ if (!ok) ok = TRUE; else
     int delivery_time = (int)(time(NULL) - start_delivery_time);
     int len;
     uschar *conf = NULL;
+
     send_rset = FALSE;
+    pipelining_active = FALSE;
 
     /* Set up confirmation if needed - applies only to SMTP */
 
index 8583ab4..804b994 100644 (file)
@@ -76,12 +76,7 @@ typedef struct {
   uschar *tls_verify_cert_hostnames;
 #endif
 #ifndef DISABLE_DKIM
-  uschar *dkim_domain;
-  uschar *dkim_private_key;
-  uschar *dkim_selector;
-  uschar *dkim_canon;
-  uschar *dkim_sign_headers;
-  uschar *dkim_strict;
+  struct ob_dkim dkim;
 #endif
 } smtp_transport_options_block;
 
index 3624af0..c04b288 100644 (file)
@@ -889,14 +889,16 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
     /* Need proper integration with the proper transport mechanism. */
     if (cutthrough.delivery)
       {
+#ifndef DISABLE_DKIM
       uschar * s;
+#endif
       if (addr->transport->filter_command)
         {
         cutthrough.delivery = FALSE;
         HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n");
         }
 #ifndef DISABLE_DKIM
-      else if ((s = ob->dkim_domain) && (s = expand_string(s)) && *s)
+      else if ((s = ob->dkim.dkim_domain) && (s = expand_string(s)) && *s)
         {
         cutthrough.delivery = FALSE;
         HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n");
@@ -1587,11 +1589,8 @@ if(cutthrough.fd < 0)
 HDEBUG(D_acl) debug_printf("----------- start cutthrough headers send -----------\n");
 
 if (!transport_headers_send(&cutthrough.addr, cutthrough.fd,
-       cutthrough.addr.transport->add_headers,
-       cutthrough.addr.transport->remove_headers,
-       &cutthrough_write_chunk, TRUE,
-       cutthrough.addr.transport->rewrite_rules,
-       cutthrough.addr.transport->rewrite_existflags))
+       cutthrough.addr.transport,
+       &cutthrough_write_chunk, TRUE))
   return FALSE;
 
 HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
index 1328a46..b3cf93c 100644 (file)
@@ -8,49 +8,49 @@
 1999-03-02 09:44:33 10HmaY-0005vi-00 CALLER@test.ex: error ignored
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == a@test.ex R=client T=send_to_server defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after RCPT TO:<b@test.ex>
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == b@test.ex R=client T=send_to_server defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after RCPT TO:<b@test.ex>
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == c@test.ex R=client T=send_to_server defer (dd): Connection timed out: SMTP timeout after RCPT TO:<b@test.ex>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == e@test.ex R=client T=send_to_server defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after RCPT TO:<f@test.ex>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == f@test.ex R=client T=send_to_server defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after RCPT TO:<f@test.ex>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == g@test.ex R=client T=send_to_server defer (dd): Connection timed out: SMTP timeout after RCPT TO:<f@test.ex>
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbA-0005vi-00 == a@test.ex R=client T=send_to_server defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@test.ex>: 451 Temp error
-1999-03-02 09:44:33 10HmbA-0005vi-00 == b@test.ex R=client T=send_to_server defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@test.ex>: 451 Temp error
+1999-03-02 09:44:33 10HmbA-0005vi-00 == h@test.ex R=client T=send_to_server defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@test.ex>: 451 Temp error
+1999-03-02 09:44:33 10HmbA-0005vi-00 == i@test.ex R=client T=send_to_server defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@test.ex>: 451 Temp error
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 ** a@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@test.ex>: 550 Perm error
-1999-03-02 09:44:33 10HmbB-0005vi-00 ** b@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@test.ex>: 550 Perm error
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** j@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@test.ex>: 550 Perm error
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** k@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@test.ex>: 550 Perm error
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= <> R=10HmbB-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbC-0005vi-00 ** CALLER@test.ex R=bounce: just discard
 1999-03-02 09:44:33 10HmbC-0005vi-00 CALLER@test.ex: error ignored
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbD-0005vi-00 == a@test.ex R=client T=send_to_server defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<a@test.ex>: 451 Temp error 1
-1999-03-02 09:44:33 10HmbD-0005vi-00 == b@test.ex R=client T=send_to_server defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<b@test.ex>: 451 Temp error 2
+1999-03-02 09:44:33 10HmbD-0005vi-00 == l@test.ex R=client T=send_to_server defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<l@test.ex>: 451 Temp error 1
+1999-03-02 09:44:33 10HmbD-0005vi-00 == m@test.ex R=client T=send_to_server defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<m@test.ex>: 451 Temp error 2
 1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbE-0005vi-00 ** a@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<a@test.ex>: 551 Perm error 1
-1999-03-02 09:44:33 10HmbE-0005vi-00 ** b@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<b@test.ex>: 551 Perm error 2
+1999-03-02 09:44:33 10HmbE-0005vi-00 ** n@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<n@test.ex>: 551 Perm error 1
+1999-03-02 09:44:33 10HmbE-0005vi-00 ** o@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<o@test.ex>: 551 Perm error 2
 1999-03-02 09:44:33 10HmbF-0005vi-00 <= <> R=10HmbE-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbF-0005vi-00 ** CALLER@test.ex R=bounce: just discard
 1999-03-02 09:44:33 10HmbF-0005vi-00 CALLER@test.ex: error ignored
 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbG-0005vi-00 == a@test.ex R=client T=send_to_server defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<a@test.ex>: 451 Temp error 1
-1999-03-02 09:44:33 10HmbG-0005vi-00 ** b@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<b@test.ex>: 551 Perm error 2
+1999-03-02 09:44:33 10HmbG-0005vi-00 == p@test.ex R=client T=send_to_server defer (-44) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<p@test.ex>: 451 Temp error 1
+1999-03-02 09:44:33 10HmbG-0005vi-00 ** q@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<q@test.ex>: 551 Perm error 2
 1999-03-02 09:44:33 10HmbH-0005vi-00 <= <> R=10HmbG-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbH-0005vi-00 ** CALLER@test.ex R=bounce: just discard
 1999-03-02 09:44:33 10HmbH-0005vi-00 CALLER@test.ex: error ignored
 1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbI-0005vi-00 ** a@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 503 Sorry perm data error
-1999-03-02 09:44:33 10HmbI-0005vi-00 ** b@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 503 Sorry perm data error
+1999-03-02 09:44:33 10HmbI-0005vi-00 ** r@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 503 Sorry perm data error
+1999-03-02 09:44:33 10HmbI-0005vi-00 ** s@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 503 Sorry perm data error
 1999-03-02 09:44:33 10HmbJ-0005vi-00 <= <> R=10HmbI-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbJ-0005vi-00 ** CALLER@test.ex R=bounce: just discard
 1999-03-02 09:44:33 10HmbJ-0005vi-00 CALLER@test.ex: error ignored
 1999-03-02 09:44:33 10HmbJ-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbK-0005vi-00 == a@test.ex R=client T=send_to_server defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 403 Sorry temp data error
-1999-03-02 09:44:33 10HmbK-0005vi-00 == b@test.ex R=client T=send_to_server defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 403 Sorry temp data error
+1999-03-02 09:44:33 10HmbK-0005vi-00 == t@test.ex R=client T=send_to_server defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 403 Sorry temp data error
+1999-03-02 09:44:33 10HmbK-0005vi-00 == u@test.ex R=client T=send_to_server defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 403 Sorry temp data error
 1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
 1999-03-02 09:44:33 10HmbL-0005vi-00 == yes@test.ex R=client T=send_to_server defer (-46) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined DATA: 403 Sorry temp data error
 1999-03-02 09:44:33 10HmbL-0005vi-00 ** n00@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<n00@test.ex>: 550 NO
 1999-03-02 09:44:33 10HmbM-0005vi-00 CALLER@test.ex: error ignored
 1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbN-0005vi-00 H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<c@test.ex>
-1999-03-02 09:44:33 10HmbN-0005vi-00 == a@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<c@test.ex>
+1999-03-02 09:44:33 10HmbN-0005vi-00 H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<c@test.ex>
+1999-03-02 09:44:33 10HmbN-0005vi-00 == a@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<c@test.ex>
 1999-03-02 09:44:33 10HmbN-0005vi-00 ** b@test.ex R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<b@test.ex>: 550 NO
-1999-03-02 09:44:33 10HmbN-0005vi-00 == c@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<c@test.ex>
-1999-03-02 09:44:33 10HmbN-0005vi-00 == d@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<c@test.ex>
-1999-03-02 09:44:33 10HmbN-0005vi-00 == e@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<c@test.ex>
+1999-03-02 09:44:33 10HmbN-0005vi-00 == c@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<c@test.ex>
+1999-03-02 09:44:33 10HmbN-0005vi-00 == d@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<c@test.ex>
+1999-03-02 09:44:33 10HmbN-0005vi-00 == e@test.ex R=client T=send_to_server defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<c@test.ex>
 1999-03-02 09:44:33 10HmbO-0005vi-00 <= <> R=10HmbN-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbO-0005vi-00 ** CALLER@test.ex R=bounce: just discard
 1999-03-02 09:44:33 10HmbO-0005vi-00 CALLER@test.ex: error ignored
index 4aac50d..bdbd414 100644 (file)
@@ -9,7 +9,7 @@
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
 1999-03-02 09:44:33 Start queue run: pid=pppp -qq
-1999-03-02 09:44:33 10HmaZ-0005vi-00 ** a@test.ex F=<CALLER@test.ex> R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@test.ex>: 550 NO
+1999-03-02 09:44:33 10HmaZ-0005vi-00 ** a@test.ex F=<CALLER@test.ex> R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@test.ex>: 550 NO
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= <> R=10HmaZ-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbA-0005vi-00 H=127.0.0.1 [127.0.0.1] Connection refused
index 0c45cc5..f76f069 100644 (file)
@@ -7,26 +7,26 @@
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmaZ-0005vi-00 H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to RCPT TO:<x@test.ex>
-1999-03-02 09:44:33 10HmaZ-0005vi-00 == x@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to RCPT TO:<x@test.ex>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined RCPT TO:<x@test.ex>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 == x@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined RCPT TO:<x@test.ex>
 1999-03-02 09:44:33 10HmaZ-0005vi-00 ** x@test.ex: 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@myhost.test.ex> R=null
 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
 1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to MAIL FROM:<CALLER@myhost.test.ex>
-1999-03-02 09:44:33 10HmbB-0005vi-00 == x@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to MAIL FROM:<CALLER@myhost.test.ex>
+1999-03-02 09:44:33 10HmbB-0005vi-00 H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined MAIL FROM:<CALLER@myhost.test.ex>
+1999-03-02 09:44:33 10HmbB-0005vi-00 == x@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined MAIL FROM:<CALLER@myhost.test.ex>
 1999-03-02 09:44:33 10HmbB-0005vi-00 ** x@test.ex: retry timeout exceeded
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= <> R=10HmbB-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbC-0005vi-00 => :blackhole: <CALLER@myhost.test.ex> R=null
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbD-0005vi-00 H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to RCPT TO:<y@test.ex>
-1999-03-02 09:44:33 10HmbD-0005vi-00 == x@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to RCPT TO:<y@test.ex>
-1999-03-02 09:44:33 10HmbD-0005vi-00 == y@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to RCPT TO:<y@test.ex>
-1999-03-02 09:44:33 10HmbD-0005vi-00 == z@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to RCPT TO:<y@test.ex>
+1999-03-02 09:44:33 10HmbD-0005vi-00 H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined RCPT TO:<y@test.ex>
+1999-03-02 09:44:33 10HmbD-0005vi-00 == x@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined RCPT TO:<y@test.ex>
+1999-03-02 09:44:33 10HmbD-0005vi-00 == y@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined RCPT TO:<y@test.ex>
+1999-03-02 09:44:33 10HmbD-0005vi-00 == z@test.ex R=remote T=smtp defer (-19) H=127.0.0.1 [127.0.0.1]: Malformed SMTP reply (an empty line) in response to pipelined RCPT TO:<y@test.ex>
 1999-03-02 09:44:33 10HmbD-0005vi-00 ** z@test.ex: retry timeout exceeded
 1999-03-02 09:44:33 10HmbD-0005vi-00 ** y@test.ex: retry timeout exceeded
 1999-03-02 09:44:33 10HmbD-0005vi-00 ** x@test.ex: retry timeout exceeded
index 17886a8..d55d679 100644 (file)
 1999-03-02 09:44:33 10HmbA-0005vi-00 ** b@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<b@x.y>: 550 NOTOK
 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbB-0005vi-00 ** a@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 550 BAD MAIL
-1999-03-02 09:44:33 10HmbB-0005vi-00 ** b@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 550 BAD MAIL
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** a@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 550 BAD MAIL
+1999-03-02 09:44:33 10HmbB-0005vi-00 ** b@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 550 BAD MAIL
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbC-0005vi-00 ** a@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 450 TEMPORARY MAIL FAIL
-1999-03-02 09:44:33 10HmbC-0005vi-00 ** b@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 450 TEMPORARY MAIL FAIL
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** a@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 450 TEMPORARY MAIL FAIL
+1999-03-02 09:44:33 10HmbC-0005vi-00 ** b@x.y R=r9 T=t1 H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 450 TEMPORARY MAIL FAIL
 1999-03-02 09:44:33 10HmbC-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
 1999-03-02 09:44:33 10HmbD-0005vi-00 => pm@p.q <postmaster@x.y> R=r9 T=t1 H=127.0.0.1 [127.0.0.1] C="250 OK"
index 9e55e5d..8d47ac2 100644 (file)
@@ -27,7 +27,7 @@
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbF-0005vi-00 == userx@x.y R=r1 T=t1 defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 452 temporary error
+1999-03-02 09:44:33 10HmbF-0005vi-00 == userx@x.y R=r1 T=t1 defer (-45) H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 452 temporary error
 1999-03-02 09:44:33 10HmbF-0005vi-00 ** userx@x.y: retry timeout exceeded
 1999-03-02 09:44:33 10HmbG-0005vi-00 <= <> R=10HmbF-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbG-0005vi-00 => :blackhole: <CALLER@myhost.test.ex> R=r0
@@ -55,8 +55,8 @@
 1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbL-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
-1999-03-02 09:44:33 10HmbN-0005vi-00 H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<userx@x.y>
-1999-03-02 09:44:33 10HmbN-0005vi-00 == userx@x.y R=r1 T=t1 defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to RCPT TO:<userx@x.y>
+1999-03-02 09:44:33 10HmbN-0005vi-00 H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<userx@x.y>
+1999-03-02 09:44:33 10HmbN-0005vi-00 == userx@x.y R=r1 T=t1 defer (-18) H=127.0.0.1 [127.0.0.1]: Remote host closed connection in response to pipelined RCPT TO:<userx@x.y>
 1999-03-02 09:44:33 10HmbN-0005vi-00 ** userx@x.y: retry timeout exceeded
 1999-03-02 09:44:33 10HmbO-0005vi-00 <= <> R=10HmbN-0005vi-00 U=EXIMUSER P=local S=sss
 1999-03-02 09:44:33 10HmbO-0005vi-00 => :blackhole: <CALLER@myhost.test.ex> R=r0
index d070f9c..4ce57b1 100644 (file)
@@ -1,9 +1,9 @@
 1999-03-02 09:44:33 10HmaX-0005vi-00 Accept non-SMTP
 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss
 1999-03-02 09:44:33 Start queue run: pid=pppp -qf
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx1@test.ex R=r1 T=t1 defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx2@test.ex R=r1 T=t1 defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
-1999-03-02 09:44:33 10HmaX-0005vi-00 == userx3@test.ex R=r1 T=t1 defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx1@test.ex R=r1 T=t1 defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx2@test.ex R=r1 T=t1 defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
+1999-03-02 09:44:33 10HmaX-0005vi-00 == userx3@test.ex R=r1 T=t1 defer (dd): Connection timed out H=127.0.0.1 [127.0.0.1]: SMTP timeout after pipelined MAIL FROM:<CALLER@myhost.test.ex> SIZE=ssss
 1999-03-02 09:44:33 End queue run: pid=pppp -qf
 1999-03-02 09:44:33 Start queue run: pid=pppp -qf
 1999-03-02 09:44:33 10HmaX-0005vi-00 => userx1@test.ex R=r1 T=t1 H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaY-0005vi-00"
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 c47ae5c..a74be60 100644 (file)
@@ -36,7 +36,7 @@ RCPT TO
 250 OK
 *sleep 2
 ****
-exim -odi a b c
+exim -odi e f g
 .
 ****
 # Temp error on MAIL
@@ -56,7 +56,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi h i
 .
 ****
 # Perm error on MAIL
@@ -76,7 +76,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi j k
 .
 ****
 # All get temp errors
@@ -96,7 +96,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi l m
 .
 ****
 # All get perm errors
@@ -116,7 +116,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi n o
 .
 ****
 # Mixed temp and perm
@@ -136,7 +136,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi p q
 .
 ****
 # Perm error on DATA after good recipients
@@ -156,7 +156,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi r s
 .
 ****
 # Temp error on DATA after good recipients
@@ -176,7 +176,7 @@ DATA
 QUIT
 250 OK
 ****
-exim -odi a b
+exim -odi t u
 .
 ****
 # Temp error on DATA after good recipients, but in first block of a
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 fe4ee2d..f9f1d68 100644 (file)
@@ -93,7 +93,7 @@ Connecting to 127.0.0.1 [127.0.0.1]:1224 ... connected
   SMTP>> QUIT
   SMTP(close)>>
 LOG: MAIN
-  ** a@test.ex F=<CALLER@test.ex> R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@test.ex>: 550 NO
+  ** a@test.ex F=<CALLER@test.ex> R=client T=send_to_server H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@test.ex>: 550 NO
 Exim version x.yz ....
 configuration file is TESTSUITE/test-config
 trusted user
index c40aa6f..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: write=dddd read=dddd
+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 b00cfd5..bfe9f62 100644 (file)
@@ -1,7 +1,7 @@
 Delivery failed: Connection refused
 Delivery failed: H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after RCPT TO:<b@x.y>: 550 NOTOK
-Delivery failed: H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 550 BAD MAIL
-Delivery failed: H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after MAIL FROM:<CALLER@myhost.test.ex>: 450 TEMPORARY MAIL FAIL
+Delivery failed: H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 550 BAD MAIL
+Delivery failed: H=127.0.0.1 [127.0.0.1]: SMTP error from remote mail server after pipelined MAIL FROM:<CALLER@myhost.test.ex>: 450 TEMPORARY MAIL FAIL
 routing file@x.y yielded a local delivery
 routing fail@x.y yielded a failed delivery: forcible fail message
 routing defer@x.y yielded a deferred delivery: forcible defer message
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 41f6bab..837941d 100644 (file)
@@ -17,8 +17,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
@@ -68,8 +68,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: *
@@ -87,8 +87,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: 
@@ -262,8 +274,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
@@ -313,8 +325,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: *
@@ -347,8 +359,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)
@@ -367,8 +379,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)
@@ -385,8 +397,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)
@@ -401,8 +413,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>)
@@ -410,8 +422,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}}
@@ -419,8 +443,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: 
@@ -476,8 +500,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
@@ -527,8 +551,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: *
@@ -561,8 +585,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)
@@ -581,8 +605,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)
@@ -599,8 +623,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)
@@ -615,8 +639,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>)
@@ -624,8 +648,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}}
@@ -633,8 +669,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 2cac1a7..a1d4d32 100644 (file)
@@ -17,8 +17,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
@@ -68,8 +68,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: *
@@ -87,8 +87,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: *
@@ -132,8 +132,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)
@@ -152,8 +152,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)
@@ -170,8 +170,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)
@@ -186,8 +186,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>)
@@ -195,8 +195,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}}
@@ -204,8 +216,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: 
@@ -261,8 +273,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
@@ -312,8 +324,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: *
@@ -346,8 +358,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)
@@ -366,8 +378,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)
@@ -384,8 +396,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)
@@ -400,8 +412,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>)
@@ -409,8 +421,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}}
@@ -418,8 +442,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: 
@@ -475,8 +499,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
@@ -526,8 +550,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: *
@@ -560,8 +584,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)
@@ -580,8 +604,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)
@@ -598,8 +622,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)
@@ -614,8 +638,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>)
@@ -623,8 +647,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}}
@@ -632,8 +668,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.
index 8633a43..f08a3fa 100644 (file)
@@ -36,7 +36,7 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 250 OK
-RCPT TO:<a@test.ex>
+RCPT TO:<e@test.ex>
 250 OK
 *sleep 2
 End of script
@@ -48,9 +48,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 451 Temp error
-RCPT TO:<a@test.ex>
+RCPT TO:<h@test.ex>
 503 No sender given
-RCPT TO:<b@test.ex>
+RCPT TO:<i@test.ex>
 503 No sender given
 DATA
 503 No envelope
@@ -65,9 +65,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 550 Perm error
-RCPT TO:<a@test.ex>
+RCPT TO:<j@test.ex>
 503 No sender given
-RCPT TO:<b@test.ex>
+RCPT TO:<k@test.ex>
 503 No sender given
 DATA
 503 No envelope
@@ -82,9 +82,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 250 OK
-RCPT TO:<a@test.ex>
+RCPT TO:<l@test.ex>
 451 Temp error 1
-RCPT TO:<b@test.ex>
+RCPT TO:<m@test.ex>
 451 Temp error 2
 DATA
 503 No recipients
@@ -99,9 +99,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 250 OK
-RCPT TO:<a@test.ex>
+RCPT TO:<n@test.ex>
 551 Perm error 1
-RCPT TO:<b@test.ex>
+RCPT TO:<o@test.ex>
 551 Perm error 2
 DATA
 503 No recipients
@@ -116,9 +116,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 250 OK
-RCPT TO:<a@test.ex>
+RCPT TO:<p@test.ex>
 451 Temp error 1
-RCPT TO:<b@test.ex>
+RCPT TO:<q@test.ex>
 551 Perm error 2
 DATA
 503 No recipients
@@ -133,9 +133,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 250 OK
-RCPT TO:<a@test.ex>
+RCPT TO:<r@test.ex>
 250 OK
-RCPT TO:<b@test.ex>
+RCPT TO:<s@test.ex>
 250 OK
 DATA
 503 Sorry perm data error
@@ -150,9 +150,9 @@ EHLO myhost.test.ex
 250 PIPELINING
 MAIL FROM:<CALLER@test.ex>
 250 OK
-RCPT TO:<a@test.ex>
+RCPT TO:<t@test.ex>
 250 OK
-RCPT TO:<b@test.ex>
+RCPT TO:<u@test.ex>
 250 OK
 DATA
 403 Sorry temp data error