&*$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"
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
&%rheader%& gives the original &"raw"& content of the header line, with no
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
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
--------------
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".
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;
}
int sep = -'/';
#endif
-for (; cb != NULL; cb = cb->next)
+for (; cb; cb = cb->next)
{
const uschar *arg;
int control_type;
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)
/*************************************************
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_)
*/
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;
}
static uschar *
fn_recipients(void)
{
+uschar * s;
gstring * g = NULL;
int i;
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;
}
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 */
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)
{
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 */
int len;
int newsize = 0;
gstring * g = NULL;
+ uschar * t;
s = read_name(name, sizeof(name), s, US"_");
/* 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
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;
+/* 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 */
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
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
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