Expansions: new ${lheader:<name>}. Bug 2272
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 1 May 2018 16:45:21 +0000 (17:45 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 1 May 2018 16:45:21 +0000 (17:45 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
doc/doc-txt/experimental-spec.txt
src/src/acl.c
src/src/expand.c
src/src/functions.h
src/src/string.c
test/confs/4560
test/log/4560
test/log/4561

index f865fc9..0d6c239 100644 (file)
@@ -9434,11 +9434,14 @@ letters appear. For example:
         &*$h_*&<&'header&~name'&>&*:*&" &&&
        "&*$bheader_*&<&'header&~name'&>&*:*&&~or&~&&&
         &*$bh_*&<&'header&~name'&>&*:*&" &&&
+       "&*$lheader_*&<&'header&~name'&>&*:*&&~or&~&&&
+        &*$lh_*&<&'header&~name'&>&*:*&"
        "&*$rheader_*&<&'header&~name'&>&*:*&&~or&~&&&
         &*$rh_*&<&'header&~name'&>&*:*&"
 .cindex "expansion" "header insertion"
 .vindex "&$header_$&"
 .vindex "&$bheader_$&"
+.vindex "&$lheader_$&"
 .vindex "&$rheader_$&"
 .cindex "header lines" "in expansion strings"
 .cindex "header lines" "character sets"
@@ -9451,7 +9454,7 @@ The newline that terminates a header line is not included in the expansion, but
 internal newlines (caused by splitting the header line over several physical
 lines) may be present.
 
-The difference between &%rheader%&, &%bheader%&, and &%header%& is in the way
+The difference between the four pairs of expansions is in the way
 the data in the header line is interpreted.
 
 .ilist
@@ -9460,6 +9463,15 @@ the data in the header line is interpreted.
 processing at all, and without the removal of leading and trailing white space.
 
 .next
+.cindex "list" "of header lines"
+&%lheader%& gives a colon-separated list, one element per header when there
+are multiple headers with a given name.
+Any embedded colon characters within an element are doubled, so normal Exim
+list-processing facilities can be used.
+The terminating newline of each element is removed; in other respects
+the content is &"raw"&.
+
+.next
 .cindex "base64 encoding" "in header lines"
 &%bheader%& removes leading and trailing white space, and then decodes base64
 or quoted-printable MIME &"words"& within the header text, but does no
index 30ec7c9..aaf9734 100644 (file)
@@ -9,6 +9,11 @@ the documentation is updated, this file is reduced to a short list.
 Version 4.92
 --------------
 
+ 1. ${l_header:<name>} and ${l_h:<name>} expansion items, giving a colon-sep
+    list when there are multiple headers having a given name.  This matters
+    when individual headers are wrapped onto multiple lines; with previous
+    facilities hard to parse.
+
 Version 4.91
 --------------
 
index ac3f1cc..15df152 100644 (file)
@@ -801,6 +801,14 @@ There are three new variables: $arc_state, $arc_state_reason, $arc_domains:
                        problematic elements may have empty list elements
   $arc_oldest_pass     lowest passing instance number of chain
 
+Example:
+  logwrite = oldest-p-ams: <${reduce {$lh_ARC-Authentication-Results:} \
+                               {} \
+                               {${if = {$arc_oldest_pass} \
+                                       {${extract {i}{${extract {1}{;}{$item}}}}} \
+                                       {$item} {$value}}} \
+                           }>
+
 Receive log lines for an ARC pass will be tagged "ARC".
 
 
index edf4fb4..d243ff4 100644 (file)
@@ -1042,33 +1042,16 @@ uschar *
 fn_hdrs_added(void)
 {
 gstring * g = NULL;
-header_line * h = acl_added_headers;
-uschar * s;
-uschar * cp;
+header_line * h;
 
-if (!h) return NULL;
-
-do
+for (h = acl_added_headers; h; h = h->next)
   {
-  s = h->text;
-  while ((cp = Ustrchr(s, '\n')) != NULL)
-    {
-    if (cp[1] == '\0') break;
-
-    /* contains embedded newline; needs doubling */
-    g = string_catn(g, s, cp-s+1);
-    g = string_catn(g, US"\n", 1);
-    s = cp+1;
-    }
-  /* last bit of header */
-
-/*XXX could we use add_listele? */
-  g = string_catn(g, s, cp-s+1);       /* newline-sep list */
+  int i = h->slen;
+  if (h->text[i-1] == '\n') i--;
+  g = string_append_listele_n(g, '\n', h->text, i);
   }
-while((h = h->next));
 
-g->s[g->ptr - 1] = '\0';       /* overwrite last newline */
-return g->s;
+return g ? g->s : NULL;
 }
 
 
@@ -2865,7 +2848,7 @@ int rc = OK;
 int sep = -'/';
 #endif
 
-for (; cb != NULL; cb = cb->next)
+for (; cb; cb = cb->next)
   {
   const uschar *arg;
   int control_type;
index 862544c..e386bbd 100644 (file)
@@ -817,6 +817,10 @@ static uschar *mtable_setid[] =
 static uschar *mtable_sticky[] =
   { US"--T", US"--t", US"-wT", US"-wt", US"r-T", US"r-t", US"rwT", US"rwt" };
 
+/* flags for find_header() */
+#define FH_EXISTS_ONLY BIT(0)
+#define FH_WANT_RAW    BIT(1)
+#define FH_WANT_LIST   BIT(2)
 
 
 /*************************************************
@@ -1529,14 +1533,20 @@ pretty trivial.
 Arguments:
   name          the name of the header, without the leading $header_ or $h_,
                 or NULL if a concatenation of all headers is required
-  exists_only   TRUE if called from a def: test; don't need to build a string;
-                just return a string that is not "" and not "0" if the header
-                exists
   newsize       return the size of memory block that was obtained; may be NULL
                 if exists_only is TRUE
-  want_raw      TRUE if called for $rh_ or $rheader_ variables; no processing,
-                other than concatenating, will be done on the header. Also used
-                for $message_headers_raw.
+  flags                FH_EXISTS_ONLY
+                 set if called from a def: test; don't need to build a string;
+                 just return a string that is not "" and not "0" if the header
+                 exists
+               FH_WANT_RAW
+                 set if called for $rh_ or $rheader_ variables; no processing,
+                 other than concatenating, will be done on the header. Also used
+                 for $message_headers_raw.
+               FH_WANT_LIST
+                 Double colon chars in the content, and replace newline with
+                 colon between each element when concatenating; returning a
+                 colon-sep list (elements might contain newlines)
   charset       name of charset to translate MIME words to; used only if
                 want_raw is false; if NULL, no translation is done (this is
                 used for $bh_ and $bheader_)
@@ -1546,121 +1556,100 @@ Returns:        NULL if the header does not exist, else a pointer to a new
 */
 
 static uschar *
-find_header(uschar *name, BOOL exists_only, int *newsize, BOOL want_raw,
-  uschar *charset)
+find_header(uschar *name, int *newsize, unsigned flags, uschar *charset)
 {
-BOOL found = name == NULL;
-int comma = 0;
-int len = found? 0 : Ustrlen(name);
-int i;
-uschar *yield = NULL;
-uschar *ptr = NULL;
-
-/* Loop for two passes - saves code repetition */
-
-for (i = 0; i < 2; i++)
-  {
-  int size = 0;
-  header_line *h;
-
-  for (h = header_list; size < header_insert_maxlen && h; h = h->next)
-    if (h->type != htype_old && h->text)  /* NULL => Received: placeholder */
-      if (!name || (len <= h->slen && strncmpic(name, h->text, len) == 0))
-        {
-        int ilen;
-        uschar *t;
-
-        if (exists_only) return US"1";      /* don't need actual string */
-        found = TRUE;
-        t = h->text + len;                  /* text to insert */
-        if (!want_raw)                      /* unless wanted raw, */
-          while (isspace(*t)) t++;          /* remove leading white space */
-        ilen = h->slen - (t - h->text);     /* length to insert */
-
-        /* Unless wanted raw, remove trailing whitespace, including the
-        newline. */
+BOOL found = !name;
+int len = name ? Ustrlen(name) : 0;
+BOOL comma = FALSE;
+header_line * h;
+gstring * g = NULL;
 
-        if (!want_raw)
-          while (ilen > 0 && isspace(t[ilen-1])) ilen--;
+for (h = header_list; h; h = h->next)
+  if (h->type != htype_old && h->text)  /* NULL => Received: placeholder */
+    if (!name || (len <= h->slen && strncmpic(name, h->text, len) == 0))
+      {
+      uschar * s, * t;
+      size_t inc;
 
-        /* Set comma = 1 if handling a single header and it's one of those
-        that contains an address list, except when asked for raw headers. Only
-        need to do this once. */
+      if (flags & FH_EXISTS_ONLY)
+       return US"1";  /* don't need actual string */
 
-        if (!want_raw && name && comma == 0 &&
-            Ustrchr("BCFRST", h->type) != NULL)
-          comma = 1;
+      found = TRUE;
+      s = h->text + len;               /* text to insert */
+      if (!(flags & FH_WANT_RAW))      /* unless wanted raw, */
+       while (isspace(*s)) s++;        /* remove leading white space */
+      t = h->text + h->slen;           /* end-point */
 
-        /* First pass - compute total store needed; second pass - compute
-        total store used, including this header. */
+      /* Unless wanted raw, remove trailing whitespace, including the
+      newline. */
 
-        size += ilen + comma + 1;  /* +1 for the newline */
+      if (flags & FH_WANT_LIST)
+       while (t > s && t[-1] == '\n') t--;
+      else if (!(flags & FH_WANT_RAW))
+       {
+       while (t > s && isspace(t[-1])) t--;
 
-        /* Second pass - concatenate the data, up to a maximum. Note that
-        the loop stops when size hits the limit. */
+       /* Set comma if handling a single header and it's one of those
+       that contains an address list, except when asked for raw headers. Only
+       need to do this once. */
 
-        if (i != 0)
-          {
-          if (size > header_insert_maxlen)
-            {
-            ilen -= size - header_insert_maxlen - 1;
-            comma = 0;
-            }
-          Ustrncpy(ptr, t, ilen);
-          ptr += ilen;
-
-          /* For a non-raw header, put in the comma if needed, then add
-          back the newline we removed above, provided there was some text in
-          the header. */
+       if (name && !comma && Ustrchr("BCFRST", h->type)) comma = TRUE;
+       }
 
-          if (!want_raw && ilen > 0)
-            {
-            if (comma != 0) *ptr++ = ',';
-            *ptr++ = '\n';
-            }
-          }
-        }
+      /* Trim the header roughly if we're approaching limits */
+      inc = t - s;
+      if ((g ? g->ptr : 0) + inc > header_insert_maxlen)
+       inc = header_insert_maxlen - (g ? g->ptr : 0);
+
+      /* For raw just copy the data; for a list, add the data as a colon-sep
+      list-element; for comma-list add as an unchecked comma,newline sep
+      list-elemment; for other nonraw add as an unchecked newline-sep list (we
+      stripped trailing WS above including the newline). We ignore the potential
+      expansion due to colon-doubling, just leaving the loop if the limit is met
+      or exceeded. */
+
+      if (flags & FH_WANT_LIST)
+        g = string_append_listele_n(g, ':', s, (unsigned)inc);
+      else if (flags & FH_WANT_RAW)
+       {
+       g = string_catn(g, s, (unsigned)inc);
+       (void) string_from_gstring(g);
+       }
+      else if (inc > 0)
+       if (comma)
+         g = string_append2_listele_n(g, US",\n", s, (unsigned)inc);
+       else
+         g = string_append2_listele_n(g, US"\n", s, (unsigned)inc);
 
-  /* At end of first pass, return NULL if no header found. Then truncate size
-  if necessary, and get the buffer to hold the data, returning the buffer size.
-  */
+      if (g && g->ptr >= header_insert_maxlen) break;
+      }
 
-  if (i == 0)
-    {
-    if (!found) return NULL;
-    if (size > header_insert_maxlen) size = header_insert_maxlen;
-    *newsize = size + 1;
-    ptr = yield = store_get(*newsize);
-    }
-  }
+if (!found) return NULL;       /* No header found */
+if (!g) return US"";
 
 /* That's all we do for raw header expansion. */
 
-if (want_raw)
-  *ptr = 0;
+*newsize = g->size;
+if (flags & FH_WANT_RAW)
+  return g->s;
 
-/* Otherwise, remove a final newline and a redundant added comma. Then we do
-RFC 2047 decoding, translating the charset if requested. The rfc2047_decode2()
-function can return an error with decoded data if the charset translation
-fails. If decoding fails, it returns NULL. */
+/* Otherwise do RFC 2047 decoding, translating the charset if requested.
+The rfc2047_decode2() function can return an error with decoded data if the
+charset translation fails. If decoding fails, it returns NULL. */
 
 else
   {
   uschar *decoded, *error;
-  if (ptr > yield && ptr[-1] == '\n') ptr--;
-  if (ptr > yield && comma != 0 && ptr[-1] == ',') ptr--;
-  *ptr = 0;
-  decoded = rfc2047_decode2(yield, check_rfc2047_length, charset, '?', NULL,
+
+  decoded = rfc2047_decode2(g->s, check_rfc2047_length, charset, '?', NULL,
     newsize, &error);
-  if (error != NULL)
+  if (error)
     {
     DEBUG(D_any) debug_printf("*** error in RFC 2047 decoding: %s\n"
-      "    input was: %s\n", error, yield);
+      "    input was: %s\n", error, g->s);
     }
-  if (decoded != NULL) yield = decoded;
+  return decoded ? decoded : g->s;
   }
-
-return yield;
 }
 
 
@@ -1711,6 +1700,7 @@ generated from a system filter, but not elsewhere. */
 static uschar *
 fn_recipients(void)
 {
+uschar * s;
 gstring * g = NULL;
 int i;
 
@@ -1718,11 +1708,10 @@ if (!enable_dollar_recipients) return NULL;
 
 for (i = 0; i < recipients_count; i++)
   {
-  /*XXX variant of list_appendele? */
-  if (i != 0) g = string_catn(g, US", ", 2);
-  g = string_cat(g, recipients_list[i].address);
+  s = recipients_list[i].address;
+  g = string_append2_listele_n(g, US", ", s, Ustrlen(s));
   }
-return string_from_gstring(g);
+return g ? g->s : NULL;
 }
 
 
@@ -1866,10 +1855,11 @@ switch (vp->type)
     return (domain == NULL)? US"" : domain + 1;
 
   case vtype_msgheaders:
-    return find_header(NULL, exists_only, newsize, FALSE, NULL);
+    return find_header(NULL, newsize, exists_only ? FH_EXISTS_ONLY : 0, NULL);
 
   case vtype_msgheaders_raw:
-    return find_header(NULL, exists_only, newsize, TRUE, NULL);
+    return find_header(NULL, newsize,
+               exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW, NULL);
 
   case vtype_msgbody:                        /* Pointer to msgbody string */
   case vtype_msgbody_end:                    /* Ditto, the end of the msg */
@@ -1934,13 +1924,16 @@ switch (vp->type)
     return tod_stamp(tod_log_datestamp_daily);
 
   case vtype_reply:                          /* Get reply address */
-    s = find_header(US"reply-to:", exists_only, newsize, TRUE,
-      headers_charset);
+    s = find_header(US"reply-to:", newsize,
+               exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW,
+               headers_charset);
     if (s) while (isspace(*s)) s++;
     if (!s || !*s)
       {
       *newsize = 0;                            /* For the *s==0 case */
-      s = find_header(US"from:", exists_only, newsize, TRUE, headers_charset);
+      s = find_header(US"from:", newsize,
+               exists_only ? FH_EXISTS_ONLY|FH_WANT_RAW : FH_WANT_RAW,
+               headers_charset);
       }
     if (s)
       {
@@ -2229,50 +2222,52 @@ switch(cond_type)
   yield == NULL we are in a skipping state, and don't care about the answer. */
 
   case ECOND_DEF:
-  if (*s != ':')
     {
-    expand_string_message = US"\":\" expected after \"def\"";
-    return NULL;
-    }
+    uschar * t;
 
-  s = read_name(name, 256, s+1, US"_");
+    if (*s != ':')
+      {
+      expand_string_message = US"\":\" expected after \"def\"";
+      return NULL;
+      }
 
-  /* Test for a header's existence. If the name contains a closing brace
-  character, this may be a user error where the terminating colon has been
-  omitted. Set a flag to adjust a subsequent error message in this case. */
+    s = read_name(name, 256, s+1, US"_");
 
-  if (Ustrncmp(name, "h_", 2) == 0 ||
-      Ustrncmp(name, "rh_", 3) == 0 ||
-      Ustrncmp(name, "bh_", 3) == 0 ||
-      Ustrncmp(name, "header_", 7) == 0 ||
-      Ustrncmp(name, "rheader_", 8) == 0 ||
-      Ustrncmp(name, "bheader_", 8) == 0)
-    {
-    s = read_header_name(name, 256, s);
-    /* {-for-text-editors */
-    if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
-    if (yield != NULL) *yield =
-      (find_header(name, TRUE, NULL, FALSE, NULL) != NULL) == testfor;
-    }
+    /* Test for a header's existence. If the name contains a closing brace
+    character, this may be a user error where the terminating colon has been
+    omitted. Set a flag to adjust a subsequent error message in this case. */
 
-  /* Test for a variable's having a non-empty value. A non-existent variable
-  causes an expansion failure. */
+    if (  ( *(t = name) == 'h'
+         || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
+         )
+       && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
+       )
+      {
+      s = read_header_name(name, 256, s);
+      /* {-for-text-editors */
+      if (Ustrchr(name, '}') != NULL) malformed_header = TRUE;
+      if (yield) *yield =
+       (find_header(name, NULL, FH_EXISTS_ONLY, NULL) != NULL) == testfor;
+      }
 
-  else
-    {
-    uschar *value = find_variable(name, TRUE, yield == NULL, NULL);
-    if (value == NULL)
+    /* Test for a variable's having a non-empty value. A non-existent variable
+    causes an expansion failure. */
+
+    else
       {
-      expand_string_message = (name[0] == 0)?
-        string_sprintf("variable name omitted after \"def:\"") :
-        string_sprintf("unknown variable \"%s\" after \"def:\"", name);
-      check_variable_error_message(name);
-      return NULL;
+      if (!(t = find_variable(name, TRUE, yield == NULL, NULL)))
+       {
+       expand_string_message = (name[0] == 0)?
+         string_sprintf("variable name omitted after \"def:\"") :
+         string_sprintf("unknown variable \"%s\" after \"def:\"", name);
+       check_variable_error_message(name);
+       return NULL;
+       }
+      if (yield) *yield = (t[0] != 0) == testfor;
       }
-    if (yield != NULL) *yield = (value[0] != 0) == testfor;
-    }
 
-  return s;
+    return s;
+    }
 
 
   /* first_delivery tests for first delivery attempt */
@@ -3979,6 +3974,7 @@ while (*s != 0)
     int len;
     int newsize = 0;
     gstring * g = NULL;
+    uschar * t;
 
     s = read_name(name, sizeof(name), s, US"_");
 
@@ -3996,17 +3992,19 @@ while (*s != 0)
 
     /* Header */
 
-    if (Ustrncmp(name, "h_", 2) == 0 ||
-        Ustrncmp(name, "rh_", 3) == 0 ||
-        Ustrncmp(name, "bh_", 3) == 0 ||
-        Ustrncmp(name, "header_", 7) == 0 ||
-        Ustrncmp(name, "rheader_", 8) == 0 ||
-        Ustrncmp(name, "bheader_", 8) == 0)
+    if (  ( *(t = name) == 'h'
+          || (*t == 'r' || *t == 'l' || *t == 'b') && *++t == 'h'
+         )
+       && (*++t == '_' || Ustrncmp(t, "eader_", 6) == 0)
+       )
       {
-      BOOL want_raw = (name[0] == 'r')? TRUE : FALSE;
-      uschar *charset = (name[0] == 'b')? NULL : headers_charset;
+      unsigned flags = *name == 'r' ? FH_WANT_RAW
+                     : *name == 'l' ? FH_WANT_RAW|FH_WANT_LIST
+                     : 0;
+      uschar * charset = *name == 'b' ? NULL : headers_charset;
+
       s = read_header_name(name, sizeof(name), s);
-      value = find_header(name, FALSE, &newsize, want_raw, charset);
+      value = find_header(name, &newsize, flags, charset);
 
       /* If we didn't find the header, and the header contains a closing brace
       character, this may be a user error where the terminating colon
index 3432d78..e333f4e 100644 (file)
@@ -481,6 +481,7 @@ extern int     stdin_ungetc(int);
 extern gstring *string_append(gstring *, int, ...) WARN_UNUSED_RESULT;
 extern gstring *string_append_listele(gstring *, uschar, const uschar *) WARN_UNUSED_RESULT;
 extern gstring *string_append_listele_n(gstring *, uschar, const uschar *, unsigned) WARN_UNUSED_RESULT;
+extern gstring *string_append2_listele_n(gstring *, const uschar *, const uschar *, unsigned) WARN_UNUSED_RESULT;
 extern uschar *string_base62(unsigned long int);
 extern gstring *string_cat (gstring *, const uschar *     ) WARN_UNUSED_RESULT;
 extern gstring *string_catn(gstring *, const uschar *, int) WARN_UNUSED_RESULT;
index 29a87c5..5a8d0e7 100644 (file)
@@ -1051,6 +1051,26 @@ return list;
 
 
 
+/* A slightly-bogus listmaker utility; the separator is a string so
+can be multiple chars - there is no checking for the element content
+containing any of the separator. */
+
+gstring *
+string_append2_listele_n(gstring * list, const uschar * sepstr,
+ const uschar * ele, unsigned len)
+{
+const uschar * sp;
+
+if (list && list->ptr)
+  list = string_cat(list, sepstr);
+
+list = string_catn(list, ele, len);
+(void) string_from_gstring(list);
+return list;
+}
+
+
+
 /************************************************/
 /* Create a growable-string with some preassigned space */
 
index 3c31539..e2095af 100644 (file)
@@ -26,8 +26,16 @@ check_data:
   warn logwrite =      arc_state:      <$arc_state>
        logwrite =      domains:        <$arc_domains>
        logwrite =      arc_oldest_pass <$arc_oldest_pass>
-       condition =     ${if def:arc_state_reason}
        logwrite =      reason:         <$arc_state_reason>
+       logwrite =      lh_A-R:         <$lh_Authentication-Results:>
+       logwrite =      lh-ams:         <$lh_ARC-Authentication-Results:>
+#      logwrite =      oldest-p-ams:   <${listextract {$arc_oldest_pass} {$lh_ARC-Authentication-Results:}}>
+       logwrite =      oldest-p-ams:   <${reduce {$lh_ARC-Authentication-Results:} \
+                                               {} \
+                                               {${if = {$arc_oldest_pass} \
+                                                       {${extract {i}{${extract {1}{;}{$item}}}}} \
+                                                       {$item} {$value}}} \
+                                       }>
 
 .ifdef OPTION
   accept
index 97677d4..153c3c7 100644 (file)
@@ -4,6 +4,10 @@
 1999-03-02 09:44:33 10HmaX-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmaX-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmaX-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmaX-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmaX-0005vi-00 lh_A-R:         < test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-0005vi-00 lh-ams:         < i=1; test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-0005vi-00 oldest-p-ams:   <i=1; test.ex; arc=none>
 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss ARC id=qwerty1234@disco-zombie.net for a@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmaX-0005vi-00 => a <a@test.ex> R=d1 T=tfile
 1999-03-02 09:44:33 10HmaY-0005vi-00 arc_state:      <none>
 1999-03-02 09:44:33 10HmaY-0005vi-00 domains:        <>
 1999-03-02 09:44:33 10HmaY-0005vi-00 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmaY-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmaY-0005vi-00 lh_A-R:         <>
+1999-03-02 09:44:33 10HmaY-0005vi-00 lh-ams:         <>
+1999-03-02 09:44:33 10HmaY-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for za@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmaZ-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmaZ-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmaZ-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 lh_A-R:         < test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 lh-ams:         < i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmaZ-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmaY-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaZ-0005vi-00"
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbA-0005vi-00 arc_state:      <none>
 1999-03-02 09:44:33 10HmbA-0005vi-00 domains:        <>
 1999-03-02 09:44:33 10HmbA-0005vi-00 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmbA-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbA-0005vi-00 lh_A-R:         <>
+1999-03-02 09:44:33 10HmbA-0005vi-00 lh-ams:         <>
+1999-03-02 09:44:33 10HmbA-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbB-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbB-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmbB-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbB-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbB-0005vi-00 lh_A-R:         < test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbB-0005vi-00 lh-ams:         < i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbB-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex
 1999-03-02 09:44:33 10HmbA-0005vi-00 => za@test.ex <zza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbB-0005vi-00"
 1999-03-02 09:44:33 10HmbA-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbC-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbC-0005vi-00 domains:        <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbC-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbC-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbC-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbC-0005vi-00 lh-ams:         < i=2; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbC-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbC-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmbB-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbC-0005vi-00"
 1999-03-02 09:44:33 10HmbB-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbD-0005vi-00 arc_state:      <none>
 1999-03-02 09:44:33 10HmbD-0005vi-00 domains:        <>
 1999-03-02 09:44:33 10HmbD-0005vi-00 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmbD-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbD-0005vi-00 lh_A-R:         <>
+1999-03-02 09:44:33 10HmbD-0005vi-00 lh-ams:         <>
+1999-03-02 09:44:33 10HmbD-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbD-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zmza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbE-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbE-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmbE-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbE-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbE-0005vi-00 lh_A-R:         < test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbE-0005vi-00 lh-ams:         < i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbE-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbE-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex
 1999-03-02 09:44:33 10HmbD-0005vi-00 => mza@test.ex <zmza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbE-0005vi-00"
 1999-03-02 09:44:33 10HmbD-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbF-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbF-0005vi-00 domains:        <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbF-0005vi-00 arc_oldest_pass <2>
+1999-03-02 09:44:33 10HmbF-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbF-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbF-0005vi-00 lh-ams:         < i=2; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbF-0005vi-00 oldest-p-ams:   <i=2; test.ex;\n  iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1>
 1999-03-02 09:44:33 10HmbF-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex
 1999-03-02 09:44:33 10HmbE-0005vi-00 => za@test.ex <mza@test.ex> R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbF-0005vi-00"
 1999-03-02 09:44:33 10HmbE-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbG-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbG-0005vi-00 domains:        <test.ex:test.ex:test.ex>
 1999-03-02 09:44:33 10HmbG-0005vi-00 arc_oldest_pass <2>
+1999-03-02 09:44:33 10HmbG-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbG-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=2) header.s=sel arc.oldest-pass=2 smtp.client-ip=127.0.0.1: test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbG-0005vi-00 lh-ams:         < i=3; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=2) header.s=sel arc.oldest-pass=2 smtp.client-ip=127.0.0.1: i=2; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbG-0005vi-00 oldest-p-ams:   <i=2; test.ex;\n  iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1>
 1999-03-02 09:44:33 10HmbG-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmbF-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbG-0005vi-00"
 1999-03-02 09:44:33 10HmbF-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbH-0005vi-00 arc_state:      <none>
 1999-03-02 09:44:33 10HmbH-0005vi-00 domains:        <>
 1999-03-02 09:44:33 10HmbH-0005vi-00 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmbH-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbH-0005vi-00 lh_A-R:         <>
+1999-03-02 09:44:33 10HmbH-0005vi-00 lh-ams:         <>
+1999-03-02 09:44:33 10HmbH-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbH-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zzmza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbI-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbI-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmbI-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbI-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbI-0005vi-00 lh_A-R:         < test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbI-0005vi-00 lh-ams:         < i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbI-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbI-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for zmza@test.ex
 1999-03-02 09:44:33 10HmbH-0005vi-00 => zmza@test.ex <zzmza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbI-0005vi-00"
 1999-03-02 09:44:33 10HmbH-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbJ-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbJ-0005vi-00 domains:        <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbJ-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 lh-ams:         < i=2; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbJ-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbJ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@test.ex
 1999-03-02 09:44:33 10HmbI-0005vi-00 => mza@test.ex <zmza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbJ-0005vi-00"
 1999-03-02 09:44:33 10HmbI-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbK-0005vi-00 domains:        <test.ex:test.ex>
 1999-03-02 09:44:33 10HmbK-0005vi-00 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbK-0005vi-00 reason:         <AMS body hash miscompare>
+1999-03-02 09:44:33 10HmbK-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=2) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbK-0005vi-00 lh-ams:         < i=2; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbK-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbK-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for za@test.ex
 1999-03-02 09:44:33 10HmbJ-0005vi-00 => za@test.ex <mza@test.ex> R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbK-0005vi-00"
 1999-03-02 09:44:33 10HmbJ-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbL-0005vi-00 domains:        <test.ex:test.ex:test.ex>
 1999-03-02 09:44:33 10HmbL-0005vi-00 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbL-0005vi-00 reason:         <i=3 (cv)>
+1999-03-02 09:44:33 10HmbL-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1: test.ex;\n    iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=2) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbL-0005vi-00 lh-ams:         < i=3; test.ex;\n iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.client-ip=127.0.0.1: i=2; test.ex;\n       iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbL-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbL-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@test.ex
 1999-03-02 09:44:33 10HmbK-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-0005vi-00"
 1999-03-02 09:44:33 10HmbK-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbM-0005vi-00 arc_state:      <none>
 1999-03-02 09:44:33 10HmbM-0005vi-00 domains:        <>
 1999-03-02 09:44:33 10HmbM-0005vi-00 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmbM-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbM-0005vi-00 lh_A-R:         <>
+1999-03-02 09:44:33 10HmbM-0005vi-00 lh-ams:         <>
+1999-03-02 09:44:33 10HmbM-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbM-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for zza@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbN-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbN-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmbN-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbN-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbN-0005vi-00 lh_A-R:         < test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbN-0005vi-00 lh-ams:         < i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbN-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbN-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@test.ex
 1999-03-02 09:44:33 10HmbM-0005vi-00 => za@test.ex <zza@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbN-0005vi-00"
 1999-03-02 09:44:33 10HmbM-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbO-0005vi-00 arc_state:      <pass>
 1999-03-02 09:44:33 10HmbO-0005vi-00 domains:        <test.ex>
 1999-03-02 09:44:33 10HmbO-0005vi-00 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmbO-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbO-0005vi-00 lh_A-R:         < test.ex;\n      iprev=pass (localhost) smtp.client-ip=127.0.0.1;\n      arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.client-ip=127.0.0.1: test.ex;\n      arc=none>
+1999-03-02 09:44:33 10HmbO-0005vi-00 lh-ams:         < i=1; test.ex;\n arc=none>
+1999-03-02 09:44:33 10HmbO-0005vi-00 oldest-p-ams:   <i=1; test.ex;\n  arc=none>
 1999-03-02 09:44:33 10HmbO-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@test.ex
 1999-03-02 09:44:33 10HmbN-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbO-0005vi-00"
 1999-03-02 09:44:33 10HmbN-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbP-0005vi-00 domains:        <convivian.com>
 1999-03-02 09:44:33 10HmbP-0005vi-00 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbP-0005vi-00 reason:         <AMS body hash miscompare>
+1999-03-02 09:44:33 10HmbP-0005vi-00 lh_A-R:         < dragon.trusteddomain.org; sender-id=fail (NotPermitted) header.sender=arc-discuss-bounces@dmarc.org; spf=fail (NotPermitted) smtp.mfrom=arc-discuss-bounces@dmarc.org: dragon.trusteddomain.org; dkim=pass\n reason="1024-bit key"\n header.d=convivian.com header.i=@convivian.com header.b=LHXEAl5e;\n dkim-adsp=pass: dragon.trusteddomain.org;\n sender-id=pass header.from=jered@convivian.com;\n spf=pass smtp.mfrom=jered@convivian.com>
+1999-03-02 09:44:33 10HmbP-0005vi-00 lh-ams:         < i=1; mailhub.convivian.com; none>
+1999-03-02 09:44:33 10HmbP-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbP-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for za@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmbQ-0005vi-00 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded]
 1999-03-02 09:44:33 10HmbQ-0005vi-00 domains:        <convivian.com:test.ex>
 1999-03-02 09:44:33 10HmbQ-0005vi-00 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbQ-0005vi-00 reason:         <i=2 (cv)>
+1999-03-02 09:44:33 10HmbQ-0005vi-00 lh_A-R:         < test.ex;\n      dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256;\n  dkim=fail (body hash mismatch; body probably modified in transit)\n              header.d=convivian.com header.s=default header.a=rsa-sha256;\n arc=fail (i=1)(AMS body hash miscompare) header.s=default arc.oldest-pass=0 smtp.client-ip=127.0.0.1: dragon.trusteddomain.org; sender-id=fail (NotPermitted) header.sender=arc-discuss-bounces@dmarc.org; spf=fail (NotPermitted) smtp.mfrom=arc-discuss-bounces@dmarc.org: dragon.trusteddomain.org; dkim=pass\n reason="1024-bit key"\n header.d=convivian.com header.i=@convivian.com header.b=LHXEAl5e;\n dkim-adsp=pass: dragon.trusteddomain.org;\n sender-id=pass header.from=jered@convivian.com;\n spf=pass smtp.mfrom=jered@convivian.com>
+1999-03-02 09:44:33 10HmbQ-0005vi-00 lh-ams:         < i=2; test.ex;\n dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256;\n  dkim=fail (body hash mismatch; body probably modified in transit)\n              header.d=convivian.com header.s=default header.a=rsa-sha256;\n arc=fail (i=1)(AMS body hash miscompare) header.s=default arc.oldest-pass=0 smtp.client-ip=127.0.0.1: i=1; mailhub.convivian.com; none>
+1999-03-02 09:44:33 10HmbQ-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbQ-0005vi-00 <= CALLER@bloggs.com H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@convivian.com for a@test.ex
 1999-03-02 09:44:33 10HmbP-0005vi-00 => a@test.ex <za@test.ex> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbQ-0005vi-00"
 1999-03-02 09:44:33 10HmbP-0005vi-00 Completed
 1999-03-02 09:44:33 10HmbR-0005vi-00 arc_state:      <none>
 1999-03-02 09:44:33 10HmbR-0005vi-00 domains:        <>
 1999-03-02 09:44:33 10HmbR-0005vi-00 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmbR-0005vi-00 reason:         <>
+1999-03-02 09:44:33 10HmbR-0005vi-00 lh_A-R:         <>
+1999-03-02 09:44:33 10HmbR-0005vi-00 lh-ams:         <>
+1999-03-02 09:44:33 10HmbR-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmbR-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss for a@test.ex
index 3770b2d..cdf581e 100644 (file)
@@ -5,6 +5,9 @@
 1999-03-02 09:44:33 10HmaX-0005vi-00 domains:        <::test.ex>
 1999-03-02 09:44:33 10HmaX-0005vi-00 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmaX-0005vi-00 reason:         <(sequence; expected i=1)>
+1999-03-02 09:44:33 10HmaX-0005vi-00 lh_A-R:         < test.ex;\n     iprev=fail;\n     auth=pass (PLAIN) smtp.auth=fred@test.ex>
+1999-03-02 09:44:33 10HmaX-0005vi-00 lh-ams:         < i=2; test.ex;\n     iprev=fail;\n     auth=pass (PLAIN) smtp.auth=fred@test.ex>
+1999-03-02 09:44:33 10HmaX-0005vi-00 oldest-p-ams:   <>
 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss id=3885245d-3bae-66a2-7a1e-0dbceae2fb50@test.ex for a@test.ex
 1999-03-02 09:44:33 Start queue run: pid=pppp
 1999-03-02 09:44:33 10HmaX-0005vi-00 => a <a@test.ex> R=d1 T=tfile