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 152bcb2384f6f96e4cb2ad20f08589c0de03e1a7..7bd5b7f9d80cda886bfda71736ee920fb91b4769 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 454d343119ab3d3ff8189c87ad404b175e078324..11b25f875bb4ee2667d6a68624cb0b3674ac4190 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 2a776b7305bccde69e4d1c67a11d894695de1cd6..587dc65084331b8370a9e7a75e97493a2b33f8b3 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 f99aa1819e4b89991fadd3fc498aac9ea24d80e5..202f7a400a3e40e783359907537eda158538a9a8 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 4e20f14f26b8ca0246f97504538edc7337fd34fe..e027a23b3213d227d3c12cf4659e0844eb14e31e 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 a0b36f7e2268fd0d5741fa9e2dc87dc355227f67..0fba962781807b8c6e221f932d788410e5dda468 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 ebbdc55e291bb7144fcd293935f3c49e00ddcb3a..4909d9f61e3d39c374af1844810c94db2e147051 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 29277baeb60acb641b4c3e53aad128931031e4a9..f468d232be298523cdd5f0c6cc56cb6df179efa5 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 ba984c1d9e51db8183af81c309a0d1e2d9ee1aba..5d0157e6385488d15a9006de33ee8cb930c37884 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 1b7b9f74c51e9f8d7eedfdf871b8d8cb496dbca1..7648f47ca4b2bc223bc3f482072341ce22956e1f 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 d17cf9b8349247b745b33a9ffccc5608363c0692..32154792e97ffb9cabb2c394d2ed457423ad7425 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 78f5a80873270d52e12b246c0a7edc8f9955ae3c..6666c52caea34fc321fc11e0867bd17aaa202b23 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 e1e6dcebf5fc10c43ff1ba51aef18a14e1a685a1..8e0a802400c0ae6268cb80793e883ae91522e8e7 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 5dc4ee9b5df4150fb5de5372af49fc644fb4d654..c9d15052588fbf8b99047f8e3835297f161f4e9c 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 54f9ef4de3fb276b5d1c2b79d6b436e163f7ea21..36a68b92cb78492d39bb0d80f3bcc179d37b60fa 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 bca597893dc7ca76bb0e2dd3cdd45c0e55213416..9624ece6af2a656667b999d8aae937497feec140 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 db522e54bdc65be91f76673919f0610d7321df7b..e3d01974a8d7c30fa9ff44c045874dc26324abd2 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 3d12988e8969ce5aa1fd4451e87541e6cdbbeafe..bbfef0632a61181905de5113a62e4770aa67ebe7 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 8583ab46835f5beb2ea42d10fe00777c8bbb5e26..804b9942fd30370c840950ccab7a29a90762039a 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 3624af0bc9e428c311d199b7ffc6acd26fd10b26..c04b288dc652d3c78c9da1dc906f45812fb9dc8b 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 1328a46dbd31d3fb71df05aabff9aa2a77e2b3b8..b3cf93c4b600148587618b808af999f01a9bf78d 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 4aac50dabf154ee0a2202c92409c35b656bb45b8..bdbd4141faba6aaa6c321ce828a553119327bd6d 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 0c45cc5d22cf50aeb36000213773ae82b8bf2f11..f76f0695bb527e59a86b372ddab804f6bf51e372 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 17886a809fc68d1748958a43b8d001560050a93d..d55d67923ef75464a47267b7a3599e417e26d90c 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 9e55e5d29b2b79d0ffddd2f2ac47c69e55171122..8d47ac2b528c100f76d7717f84553bcc54d46fd1 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 d070f9c8cabbfdb9f77acacd36c2165acca6b555..4ce57b114546b2cf0ac1bc2bc511c856cda0f407 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 278a38660519afadefd1ae19eef06594dae3d9aa..dafcba7f08154b9ecaf82b0b60d93fa3ece04af4 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 c47ae5c9e58b48961f98101183c54b3388d58410..a74be606f81c16a9500753d143b2d7953a0b5b3d 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 19ed3479ae16cae053e3e0e7407b9e3c2f678458..317b4bd0adf15e6c83c47761caec7d1cfc9e1024 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 e763efc0f502bae33ef0cb330f3ba53e7c8ddb70..197256b81a9fb3642348ccef701da899a6f30814 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 fe4ee2df9ddd6a0d0f572f7132164b0c95072877..f9f1d6849c7e0a819e6c5aec26e642dcec87f1eb 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 c40aa6f52d7ae4b7018d1f57f58703b6ac2ce562..941e8f89c35abb12ede466a6fc19e35c8e1e63c8 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 9f95393f364a4538ce49fc9d676dfeadf18c85c3..24a4fcd4d8a6d9c56dd0bc0d9d4a6851dd200452 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 b00cfd572cc3d1c48062bd22f61b99e093ce164c..bfe9f62183d3ceb2b07428b5c02231325c81dc1b 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 a95583ab70165d07ffd893f9dcda79f00773a22c..f950e456ca1c6ba71599bb58f3cbec917a105d24 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 41f6bab6f0cd33000170d50073305336633f74d6..837941d171f1a35ad8e13a20dd6cceae2c36f0cf 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 2cac1a73f016e389b9419cfdccb0dbfec67b42b7..a1d4d32678a8e8e57b599d8a53531164a2b2d449 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 0bbd4c75497e8fb385d05e58de88f18bd0919a12..a19cc526c85ff96673d3f5b07d44bc1fb4070be0 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 8633a43eed9f959bc6f32abf23fa82d5418ecc9f..f08a3fab64282a45ac4b21090a93ebb9c6d3a691 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