&*$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
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
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