[exim-cvs] DMARC: add ARC info to history records

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] DMARC: add ARC info to history records
Gitweb: https://git.exim.org/exim.git/commitdiff/6d9b05ae272ca2122b48451c317d601e449af932
Commit:     6d9b05ae272ca2122b48451c317d601e449af932
Parent:     21b172df101c2c52faf0cc56a502395451975be9
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Thu Aug 24 20:22:43 2023 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sun Aug 27 21:15:33 2023 +0100


    DMARC: add ARC info to history records
---
 doc/doc-txt/ChangeLog                |   2 +
 src/src/arc.c                        | 312 ++++++++++++++++++++++++-----------
 src/src/dkim.c                       |   4 +-
 src/src/dmarc.c                      |  42 +++--
 src/src/dmarc.h                      |   4 +
 src/src/functions.h                  |   3 +
 src/src/spf.c                        |  35 ++--
 test/aux-fixed/4690.tldfile          |   1 +
 test/confs/4560                      |   6 +-
 test/confs/{4560 => 4690}            |  51 +++---
 test/log/4560                        |  92 +++++------
 test/log/4561                        |   4 +-
 test/log/4562                        |   8 +-
 test/log/4563                        |   4 +-
 test/log/4690                        |  57 +++++++
 test/mail/4560.a                     |  88 +++++-----
 test/mail/4565.a                     |   8 +-
 test/mail/4690.a                     |  67 ++++++++
 test/scripts/4500-DKIM/4500          |   2 +-
 test/scripts/4690-DMARC-ARC/4690     |  45 +++++
 test/scripts/4690-DMARC-ARC/REQUIRES |   3 +
 test/stdout/4650                     |   4 +
 test/stdout/4690                     |  86 ++++++++++
 23 files changed, 681 insertions(+), 247 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 948e51d73..625c6d426 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -179,6 +179,8 @@ JH/34 Bug 3013: Fix use of $recipients within arguments for ${run...}.
 JH/35 Bug 3014: GnuTLS: fix expiry date for an auto-generated server
       certificate.  Find and fix by Andreas Metzler.


+JH/36 Add ARC info to DMARC hostory recordsl
+

Exim version 4.96
-----------------
diff --git a/src/src/arc.c b/src/src/arc.c
index ef44672f8..611697021 100644
--- a/src/src/arc.c
+++ b/src/src/arc.c
@@ -18,6 +18,10 @@
# include "pdkim/pdkim.h"
# include "pdkim/signing.h"

+# ifdef SUPPORT_DMARC
+# include "dmarc.h"
+# endif
+
extern pdkim_ctx * dkim_verify_ctx;
extern pdkim_ctx dkim_sign_ctx;

@@ -50,6 +54,7 @@ typedef struct arc_line {
   blob        s;
   blob        c;
   blob        l;
+  blob        ip;


   /* tag content sub-portions */
   blob        a_algo;
@@ -89,12 +94,43 @@ typedef struct arc_ctx {
 #define HDR_AR        US"Authentication-Results:"
 #define HDRLEN_AR    23


+typedef enum line_extract {
+ le_instance_only,
+ le_instance_plus_ip,
+ le_all
+} line_extract_t;
+
static time_t now;
static time_t expire;
static hdr_rlist * headers_rlist;
static arc_ctx arc_sign_ctx = { NULL };
static arc_ctx arc_verify_ctx = { NULL };

+/* We build a context for either Sign or Verify.
+
+For Verify, it's a fresh new one for ACL verify=arc - there is no connection
+with the single line handling done during reception via the DKIM feed.
+
+For Verify we do it twice; initially during reception (via the DKIM feed)
+and then later for the full verification.
+
+The former only looks at AMS headers, to discover what hash(es) we need done for
+ARC on the message body; we call back to the DKIM code to set up so that it does
+them for us during reception. That call needs info from many of the AMS tags;
+arc_parse_line() for only the AMS is called asking for all the tag types.
+That context is then discarded.
+
+Later, for Verify, we look at ARC headers again and then grab the hash result
+from the DKIM layer. arc_parse_line() is called for all 3 line types,
+gathering info for only 'i' and 'ip' tags from AAR headers,
+for all tag types from AMS and AS headers.
+
+
+For Sign, while running through the existing headers (before adding any for
+this signing operation, we "take copies" of the headers, we call
+arc_parse_line() gathering only the 'i' tag (instance) information.
+*/
+

/******************************************************************************/

@@ -188,18 +224,23 @@ return NULL;


/* Inspect a header line, noting known tag fields.
-Check for duplicates. */
+Check for duplicate named tags.
+
+See the file block comment for how this is used.
+
+Return: NULL for good, or an error string
+*/

 static uschar *
-arc_parse_line(arc_line * al, header_line * h, unsigned off, BOOL instance_only)
+arc_parse_line(arc_line * al, header_line * h, unsigned off, line_extract_t l_ext)
 {
 uschar * s = h->text + off;
-uschar * r = NULL;    /* compiler-quietening */
+uschar * r = NULL;
 uschar c;


al->complete = h;

-if (!instance_only)
+if (l_ext == le_all)        /* need to grab rawsig_no_b */
   {
   al->rawsig_no_b_val.data = store_get(h->slen + 1, GET_TAINTED);
   memcpy(al->rawsig_no_b_val.data, h->text, off);    /* copy the header name blind */
@@ -218,75 +259,77 @@ while ((c = *s))
   uschar * bstart = NULL, * bend;


/* tag-spec = [FWS] tag-name [FWS] "=" [FWS] tag-value [FWS] */
+ /*X or just a naked FQDN, in a AAR ! */

-  s = skip_fws(s);                        /* FWS */
+  s = skip_fws(s);                        /* leading FWS */
   if (!*s) break;
-/* debug_printf("%s: consider '%s'\n", __FUNCTION__, s); */
   tagchar = *s++;
-  s = skip_fws(s);                        /* FWS */
-  if (!*s) break;
+  if (!*(s = skip_fws(s))) break;                /* FWS */


-  if (!instance_only || tagchar == 'i') switch (tagchar)
+  switch (tagchar)
     {
     case 'a':                /* a= AMS algorithm */
-      {
-      if (*s != '=') return US"no 'a' value";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, a), &s)) return US"a tag dup";
-
-      /* substructure: algo-hash   (eg. rsa-sha256) */
-
-      t = al->a_algo.data = al->a.data;
-      while (*t != '-')
-    if (!*t++ || ++i > al->a.len) return US"no '-' in 'a' value";
-      al->a_algo.len = i;
-      if (*t++ != '-') return US"no '-' in 'a' value";
-      al->a_hash.data = t;
-      al->a_hash.len = al->a.len - i - 1;
-      }
+      if (l_ext == le_all && *s == '=')
+    {
+    if (arc_insert_tagvalue(al, offsetof(arc_line, a), &s)) return US"a tag dup";
+
+    /* substructure: algo-hash   (eg. rsa-sha256) */
+
+    t = al->a_algo.data = al->a.data;
+    while (*t != '-')
+      if (!*t++ || ++i > al->a.len) return US"no '-' in 'a' value";
+    al->a_algo.len = i;
+    if (*t++ != '-') return US"no '-' in 'a' value";
+    al->a_hash.data = t;
+    al->a_hash.len = al->a.len - i - 1;
+    }
       break;
     case 'b':
-      {
-      gstring * g = NULL;
-
-      switch (*s)
+      if (l_ext == le_all)
     {
-    case '=':            /* b= AMS signature */
-      if (al->b.data) return US"already b data";
-      bstart = s+1;
-
-      /* The signature can have FWS inserted in the content;
-      make a stripped copy */
-
-      while ((c = *++s) && c != ';')
-        if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
-          g = string_catn(g, s, 1);
-      if (!g) return US"no b= value";
-      al->b.len = len_string_from_gstring(g, &al->b.data);
-      gstring_release_unused(g);
-      bend = s;
-      break;
-    case 'h':            /* bh= AMS body hash */
-      s = skip_fws(++s);                    /* FWS */
-      if (*s != '=') return US"no bh value";
-      if (al->bh.data) return US"already bh data";
-
-      /* The bodyhash can have FWS inserted in the content;
-      make a stripped copy */
-
-      while ((c = *++s) && c != ';')
-        if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
-          g = string_catn(g, s, 1);
-      if (!g) return US"no bh= value";
-      al->bh.len = len_string_from_gstring(g, &al->bh.data);
-      gstring_release_unused(g);
-      break;
-    default:
-      return US"b? tag";
+    gstring * g = NULL;
+
+    switch (*s)
+      {
+      case '=':            /* b= AMS signature */
+        if (al->b.data) return US"already b data";
+        bstart = s+1;
+
+        /* The signature can have FWS inserted in the content;
+        make a stripped copy */
+
+        while ((c = *++s) && c != ';')
+          if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+        g = string_catn(g, s, 1);
+        if (!g) return US"no b= value";
+        al->b.len = len_string_from_gstring(g, &al->b.data);
+        gstring_release_unused(g);
+        bend = s;
+        break;
+      case 'h':            /* bh= AMS body hash */
+        s = skip_fws(++s);                    /* FWS */
+        if (*s == '=')
+          {
+          if (al->bh.data) return US"already bh data";
+
+          /* The bodyhash can have FWS inserted in the content;
+          make a stripped copy */
+
+          while ((c = *++s) && c != ';')
+        if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+          g = string_catn(g, s, 1);
+          if (!g) return US"no bh= value";
+          al->bh.len = len_string_from_gstring(g, &al->bh.data);
+          gstring_release_unused(g);
+          }
+        break;
+      default:
+        return US"b? tag";
+      }
     }
-      }
       break;
     case 'c':
-      switch (*s)
+      if (l_ext == le_all) switch (*s)
     {
     case '=':            /* c= AMS canonicalisation */
       if (arc_insert_tagvalue(al, offsetof(arc_line, c), &s)) return US"c tag dup";
@@ -309,43 +352,62 @@ while ((c = *s))
         }
       break;
     case 'v':            /* cv= AS validity */
-      if (*++s != '=') return US"cv tag val";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, cv), &s)) return US"cv tag dup";
+      s = skip_fws(s);
+      if (*++s == '=')
+        if (arc_insert_tagvalue(al, offsetof(arc_line, cv), &s))
+          return US"cv tag dup";
       break;
-    default:
-      return US"c? tag";
     }
       break;
     case 'd':                /* d= AMS domain */
-      if (*s != '=') return US"d tag val";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, d), &s)) return US"d tag dup";
+      if (l_ext == le_all && *s == '=')
+    if (arc_insert_tagvalue(al, offsetof(arc_line, d), &s))
+      return US"d tag dup";
       break;
     case 'h':                /* h= AMS headers */
-      if (*s != '=') return US"h tag val";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, h), &s)) return US"h tag dup";
+      if (*s == '=')
+    if (arc_insert_tagvalue(al, offsetof(arc_line, h), &s))
+      return US"h tag dup";
       break;
     case 'i':                /* i= ARC set instance */
-      if (*s != '=') return US"i tag val";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, i), &s)) return US"i tag dup";
-      if (instance_only) goto done;
+      if (*s == '=')
+    {
+    if (arc_insert_tagvalue(al, offsetof(arc_line, i), &s))
+      return US"i tag dup";
+    if (l_ext == le_instance_only)
+      goto done;            /* early-out */
+    }
       break;
     case 'l':                /* l= bodylength */
-      if (*s != '=') return US"l tag val";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, l), &s)) return US"l tag dup";
+      if (l_ext == le_all && *s == '=')
+    if (arc_insert_tagvalue(al, offsetof(arc_line, l), &s))
+      return US"l tag dup";
       break;
-    case 's':                /* s= AMS selector */
-      if (*s != '=') return US"s tag val";
-      if (arc_insert_tagvalue(al, offsetof(arc_line, s), &s)) return US"s tag dup";
+    case 's':
+      if (*s == '=' && l_ext == le_all)
+    {
+    if (arc_insert_tagvalue(al, offsetof(arc_line, s), &s))
+      return US"s tag dup";
+    }
+      else if (  l_ext == le_instance_plus_ip
+          && Ustrncmp(s, "mtp.remote-ip", 13) == 0)
+    {            /* smtp.remote-ip= AAR reception data */
+    s += 13;
+    s = skip_fws(s);
+    if (*s != '=') return US"smtp.remote_ip tag val";
+    if (arc_insert_tagvalue(al, offsetof(arc_line, ip), &s))
+      return US"ip tag dup";
+    }
       break;
     }


-  while ((c = *s) && c != ';') s++;
+  while ((c = *s) && c != ';') s++;    /* end of this tag=value */
   if (c) s++;                /* ; after tag-spec */


/* for all but the b= tag, copy the field including FWS. For the b=,
drop the tag content. */

-  if (!instance_only)
+  if (r)
     if (bstart)
       {
       size_t n = bstart - fieldstart;
@@ -366,7 +428,7 @@ while ((c = *s))
       }
   }


-if (!instance_only)
+if (r)
*r = '\0';

done:
@@ -381,7 +443,7 @@ adding instances as needed and checking for duplicate lines.

static uschar *
arc_insert_hdr(arc_ctx * ctx, header_line * h, unsigned off, unsigned hoff,
- BOOL instance_only, arc_line ** alp_ret)
+ line_extract_t l_ext, arc_line ** alp_ret)
{
unsigned i;
arc_set * as;
@@ -390,10 +452,10 @@ uschar * e;

memset(al, 0, sizeof(arc_line));

-if ((e = arc_parse_line(al, h, off, instance_only)))
+if ((e = arc_parse_line(al, h, off, l_ext)))
   {
   DEBUG(D_acl) if (e) debug_printf("ARC: %s\n", e);
-  return US"line parse";
+  return string_sprintf("line parse: %s", e);
   }
 if (!(i = arc_instance_from_hdr(al)))    return US"instance find";
 if (i > 50)                return US"overlarge instance number";
@@ -407,9 +469,10 @@ return NULL;




+/* Called for both Sign and Verify */

static const uschar *
-arc_try_header(arc_ctx * ctx, header_line * h, BOOL instance_only)
+arc_try_header(arc_ctx * ctx, header_line * h, BOOL is_signing)
{
const uschar * e;

@@ -425,10 +488,10 @@ if (strncmpic(ARC_HDR_AAR, h->text, ARC_HDRLEN_AAR) == 0)
     debug_printf("ARC: found AAR: %.*s\n", len, h->text);
     }
   if ((e = arc_insert_hdr(ctx, h, ARC_HDRLEN_AAR, offsetof(arc_set, hdr_aar),
-              TRUE, NULL)))
+          is_signing ? le_instance_only : le_instance_plus_ip, NULL)))
     {
     DEBUG(D_acl) debug_printf("inserting AAR: %s\n", e);
-    return US"inserting AAR";
+    return string_sprintf("inserting AAR: %s", e);
     }
   }
 else if (strncmpic(ARC_HDR_AMS, h->text, ARC_HDRLEN_AMS) == 0)
@@ -444,10 +507,10 @@ else if (strncmpic(ARC_HDR_AMS, h->text, ARC_HDRLEN_AMS) == 0)
     debug_printf("ARC: found AMS: %.*s\n", len, h->text);
     }
   if ((e = arc_insert_hdr(ctx, h, ARC_HDRLEN_AMS, offsetof(arc_set, hdr_ams),
-              instance_only, &ams)))
+          is_signing ? le_instance_only : le_all, &ams)))
     {
     DEBUG(D_acl) debug_printf("inserting AMS: %s\n", e);
-    return US"inserting AMS";
+    return string_sprintf("inserting AMS: %s", e);
     }


   /* defaults */
@@ -468,10 +531,10 @@ else if (strncmpic(ARC_HDR_AS, h->text, ARC_HDRLEN_AS) == 0)
     debug_printf("ARC: found AS: %.*s\n", len, h->text);
     }
   if ((e = arc_insert_hdr(ctx, h, ARC_HDRLEN_AS, offsetof(arc_set, hdr_as),
-              instance_only, NULL)))
+        is_signing ? le_instance_only : le_all, NULL)))
     {
     DEBUG(D_acl) debug_printf("inserting AS: %s\n", e);
-    return US"inserting AS";
+    return string_sprintf("inserting AS: %s", e);
     }
   }
 return NULL;
@@ -481,7 +544,8 @@ return NULL;


/* Gather the chain of arc sets from the headers.
Check for duplicates while that is done. Also build the
-reverse-order headers list;
+reverse-order headers list.
+Called on an ACL verify=arc condition.

Return: ARC state if determined, eg. by lack of any ARC chain.
*/
@@ -1194,7 +1258,8 @@ arc_line * al = (arc_line *)(as+1);
header_line * h = (header_line *)(al+1);

 g = string_catn(g, ARC_HDR_AAR, ARC_HDRLEN_AAR);
-g = string_fmt_append(g, " i=%d; %s;\r\n\t", instance, identity);
+g = string_fmt_append(g, " i=%d; %s; smtp.remote-ip=%s;\r\n\t",
+             instance, identity, sender_host_address);
 g = string_catn(g, US ar->data, ar->len);


 h->slen = g->ptr - aar_off;
@@ -1773,7 +1838,7 @@ DEBUG(D_receive) debug_printf("ARC: spotted AMS header\n");
 memset(&al, 0, sizeof(arc_line));
 h.next = NULL;
 h.slen = len_string_from_gstring(g, &h.text);
-if ((errstr = arc_parse_line(&al, &h, ARC_HDRLEN_AMS, FALSE)))
+if ((errstr = arc_parse_line(&al, &h, ARC_HDRLEN_AMS, le_all)))
   {
   DEBUG(D_acl) if (errstr) debug_printf("ARC: %s\n", errstr);
   goto badline;
@@ -1887,13 +1952,70 @@ if (arc_state)
     }
   else if (arc_state_reason)
     g = string_append(g, 3, US" (", arc_state_reason, US")");
-  DEBUG(D_acl) debug_printf("ARC:  authres '%.*s'\n",
+  DEBUG(D_acl) debug_printf("ARC:\tauthres '%.*s'\n",
           gstring_length(g) - start - 3, g->s + start + 3);
   }
 else
-  DEBUG(D_acl) debug_printf("ARC:  no authres\n");
+  DEBUG(D_acl) debug_printf("ARC:\tno authres\n");
+return g;
+}
+
+
+#  ifdef SUPPORT_DMARC
+/* Append a DMARC history record pair for ARC, to the given history set */
+
+gstring *
+arc_dmarc_hist_append(gstring * g)
+{
+if (arc_state)
+  {
+  BOOL first = TRUE;
+  int i = Ustrcmp(arc_state, "pass") == 0 ? ARES_RESULT_PASS
+      : Ustrcmp(arc_state, "fail") == 0 ? ARES_RESULT_FAIL
+      : ARES_RESULT_UNKNOWN;
+  g = string_fmt_append(g, "arc %d\n", i);
+  g = string_fmt_append(g, "arc_policy %d json[",
+              i == ARES_RESULT_PASS ? DMARC_ARC_POLICY_RESULT_PASS
+              : i == ARES_RESULT_FAIL ? DMARC_ARC_POLICY_RESULT_FAIL
+              : DMARC_ARC_POLICY_RESULT_UNUSED);
+  /*XXX would we prefer this backwards? */
+  for (arc_set * as = arc_verify_ctx.arcset_chain; as;
+    as = as->next, first = FALSE)
+    {
+    arc_line * line = as->hdr_as;
+    if (line)
+      {
+      blob * d = &line->d;
+      blob * s = &line->s;
+
+      if (!first)
+    g = string_catn(g, US",", 1);
+
+      g = string_fmt_append(g, " (\"i\":%u,"            /*)*/
+                " \"d\":\"%.*s\","
+                " \"s\":\"%.*s\"",
+          as->instance,
+          d->data ? (int)d->len : 0, d->data && d->len ? d->data : US"",
+          s->data ? (int)s->len : 0, s->data && s->len ? s->data : US""
+               );
+      if ((line = as->hdr_aar))
+    {
+    blob * ip = &line->ip;
+    if (ip->data && ip->len)
+      g = string_fmt_append(g, ", \"ip\":\"%.*s\"", (int)ip->len, ip->data);
+    }
+
+      g = string_catn(g, US")", 1);
+      }
+    }
+  g = string_catn(g, US" ]\n", 3);
+  }
+else
+  g = string_fmt_append(g, "arc %d\narc_policy $d json:[]\n",
+            ARES_RESULT_UNKNOWN, DMARC_ARC_POLICY_RESULT_UNUSED);
 return g;
 }
+#  endif



# endif /* DISABLE_DKIM */
diff --git a/src/src/dkim.c b/src/src/dkim.c
index 068b802e0..a49c8d764 100644
--- a/src/src/dkim.c
+++ b/src/src/dkim.c
@@ -885,9 +885,9 @@ for (pdkim_signature * sig = dkim_signatures; sig; sig = sig->next)

 DEBUG(D_acl)
   if (gstring_length(g) == start)
-    debug_printf("DKIM: no authres\n");
+    debug_printf("DKIM:\tno authres\n");
   else
-    debug_printf("DKIM: authres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
+    debug_printf("DKIM:\tauthres '%.*s'\n", g->ptr - start - 3, g->s + start + 3);
 return g;
 }


diff --git a/src/src/dmarc.c b/src/src/dmarc.c
index 070095660..042ebe982 100644
--- a/src/src/dmarc.c
+++ b/src/src/dmarc.c
@@ -97,7 +97,8 @@ int *netmask   = NULL;   /* Ignored */
 int is_ipv6    = 0;


 /* Set some sane defaults.  Also clears previous results when
- * multiple messages in one connection. */
+multiple messages in one connection. */
+
 dmarc_pctx         = NULL;
 dmarc_status       = US"none";
 dmarc_abort        = FALSE;
@@ -153,11 +154,12 @@ return OK;
 }



-/* dmarc_store_data stores the header data so that subsequent
-dmarc_process can access the data */
+/* dmarc_store_data stores the header data so that subsequent dmarc_process can
+access the data.
+Called after the entire message has been received, with the From: header. */

int
-dmarc_store_data(header_line *hdr)
+dmarc_store_data(header_line * hdr)
{
/* No debug output because would change every test debug output */
if (!f.dmarc_disable_verify)
@@ -167,7 +169,7 @@ return OK;


 static void
-dmarc_send_forensic_report(u_char **ruf)
+dmarc_send_forensic_report(u_char ** ruf)
 {
 uschar *recipient, *save_sender;
 BOOL  send_status = FALSE;
@@ -254,15 +256,19 @@ if (!dmarc_history_file)
   return DMARC_HIST_DISABLED;
   }
 if (!host_checking)
-  if ((history_file_fd = log_open_as_exim(dmarc_history_file)) < 0)
+  {
+  uschar * s = string_copy(dmarc_history_file);        /* need a writeable copy */
+  if ((history_file_fd = log_open_as_exim(s)) < 0)
     {
     log_write(0, LOG_MAIN|LOG_PANIC,
           "failure to create DMARC history file: %s: %s",
-          dmarc_history_file, strerror(errno));
+          s, strerror(errno));
     return DMARC_HIST_FILE_ERR;
     }
+  }
+
+/* Generate the contents of the history file entry */


-/* Generate the contents of the history file */
g = string_fmt_append(NULL,
"job %s\nreporter %s\nreceived %ld\nipaddr %s\nfrom %s\nmfrom %s\n",
message_id, primary_hostname, time(NULL), sender_host_address,
@@ -301,6 +307,15 @@ g = string_fmt_append(g, "sp %d\n", tmp_ans);
g = string_fmt_append(g, "align_dkim %d\nalign_spf %d\naction %d\n",
da, sa, action);

+#if DMARC_API >= 100400
+# ifdef EXPERIMENTAL_ARC
+g = arc_dmarc_hist_append(g);
+# else
+g = string_fmt_append(g, "arc %d\narc_policy $d json:[]\n",
+              ARES_RESULT_UNKNOWN, DMARC_ARC_POLICY_RESULT_UNUSED);
+# endif
+#endif
+
 /* Write the contents to the history file */
 DEBUG(D_receive)
   {
@@ -331,7 +346,8 @@ return DMARC_HIST_OK;


/* dmarc_process adds the envelope sender address to the existing
context (if any), retrieves the result, sets up expansion
-strings and evaluates the condition outcome. */
+strings and evaluates the condition outcome.
+Called for the first ACL dmarc= condition. */

 int
 dmarc_process(void)
@@ -536,7 +552,7 @@ The EDITME provides a DMARC_API variable */
       break;
     }


-/* Store the policy string in an expandable variable. */
+ /* Store the policy string in an expandable variable. */

   libdm_status = opendmarc_policy_fetch_p(dmarc_pctx, &tmp_ans);
   for (c = 0; dmarc_policy_description[c].name; c++)
@@ -661,10 +677,16 @@ authres_dmarc(gstring * g)
 {
 if (f.dmarc_has_been_checked)
   {
+  int start = 0;        /* Compiler quietening */
+  DEBUG(D_acl) start = gstring_length(g);
   g = string_append(g, 2, US";\n\tdmarc=", dmarc_pass_fail);
   if (header_from_sender)
     g = string_append(g, 2, US" header.from=", header_from_sender);
+  DEBUG(D_acl) debug_printf("DMARC:\tauthres '%.*s'\n",
+          gstring_length(g) - start - 3, g->s + start + 3);
   }
+else
+  DEBUG(D_acl) debug_printf("DMARC:\tno authres\n");
 return g;
 }


diff --git a/src/src/dmarc.h b/src/src/dmarc.h
index 7ce0ca953..fa366dd06 100644
--- a/src/src/dmarc.h
+++ b/src/src/dmarc.h
@@ -58,4 +58,8 @@ uschar *dmarc_exim_expand_defaults(int);
#define ARES_RESULT_UNKNOWN 11
#define ARES_RESULT_DISCARD 12

+#define    DMARC_ARC_POLICY_RESULT_PASS    0
+#define    DMARC_ARC_POLICY_RESULT_UNUSED    1
+#define    DMARC_ARC_POLICY_RESULT_FAIL    2
+
 #endif /* SUPPORT_DMARC */
diff --git a/src/src/functions.h b/src/src/functions.h
index 0b030e4fe..5db9bc610 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -109,6 +109,9 @@ extern tree_node *acl_var_create(uschar *);
 extern void    acl_var_write(uschar *, uschar *, void *);


 #ifdef EXPERIMENTAL_ARC
+# ifdef SUPPORT_DMARC
+extern gstring *arc_dmarc_hist_append(gstring *);
+# endif
 extern void   *arc_ams_setup_sign_bodyhash(void);
 extern const uschar *arc_header_feed(gstring *, BOOL);
 extern gstring *arc_sign(const uschar *, gstring *, uschar **);
diff --git a/src/src/spf.c b/src/src/spf.c
index 6f0917a9c..3d83f07ba 100644
--- a/src/src/spf.c
+++ b/src/src/spf.c
@@ -401,20 +401,31 @@ gstring *
 authres_spf(gstring * g)
 {
 uschar * s;
-if (!spf_result) return g;
-
-g = string_append(g, 2, US";\n\tspf=", spf_result);
-if (spf_result_guessed)
-  g = string_cat(g, US" (best guess record for domain)");
+if (spf_result)
+  {
+  int start = 0;        /* Compiler quietening */
+  DEBUG(D_acl) start = gstring_length(g);


-s = expand_string(US"$sender_address_domain");
-if (s && *s)
-  return string_append(g, 2, US" smtp.mailfrom=", s);
+  g = string_append(g, 2, US";\n\tspf=", spf_result);
+  if (spf_result_guessed)
+    g = string_cat(g, US" (best guess record for domain)");


-s = sender_helo_name;
-return s && *s
-  ? string_append(g, 2, US" smtp.helo=", s)
-  : string_cat(g, US" smtp.mailfrom=<>");
+  s = expand_string(US"$sender_address_domain");
+  if (s && *s)
+    g = string_append(g, 2, US" smtp.mailfrom=", s);
+  else
+    {
+    s = sender_helo_name;
+    g = s && *s
+      ? string_append(g, 2, US" smtp.helo=", s)
+      : string_cat(g, US" smtp.mailfrom=<>");
+    }
+  DEBUG(D_acl) debug_printf("SPF:\tauthres '%.*s'\n",
+          gstring_length(g) - start - 3, g->s + start + 3);
+  }
+else
+  DEBUG(D_acl) debug_printf("SPF:\tno authres\n");
+return g;
 }



diff --git a/test/aux-fixed/4690.tldfile b/test/aux-fixed/4690.tldfile
new file mode 100644
index 000000000..a9eb3bbf4
--- /dev/null
+++ b/test/aux-fixed/4690.tldfile
@@ -0,0 +1 @@
+ac
diff --git a/test/confs/4560 b/test/confs/4560
index 8cffd65cf..d6627bae5 100644
--- a/test/confs/4560
+++ b/test/confs/4560
@@ -29,9 +29,9 @@ check_data:
     logwrite =    arc_oldest_pass <$arc_oldest_pass>
     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:} \
+    logwrite =    lh-AAR:         <$lh_ARC-Authentication-Results:>
+#    logwrite =    oldest-p-AAR:   <${listextract {$arc_oldest_pass} {$lh_ARC-Authentication-Results:}}>
+    logwrite =    oldest-p-AAR:   <${reduce {$lh_ARC-Authentication-Results:} \
                         {} \
                         {${if = {$arc_oldest_pass} \
                             {${extract {i}{${extract {1}{;}{$item}}}}} \
diff --git a/test/confs/4560 b/test/confs/4690
similarity index 61%
copy from test/confs/4560
copy to test/confs/4690
index 8cffd65cf..ad4ac7279 100644
--- a/test/confs/4560
+++ b/test/confs/4690
@@ -1,15 +1,27 @@
-# Exim test configuration 4560
+# Exim test configuration 4690


SERVER=
-VALUE=
-INSERT=

-.include DIR/aux-var/std_conf_prefix
+exim_path = EXIM_PATH
+keep_environment =
+host_lookup_order = bydns
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/SERVER%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+chunking_advertise_hosts = *
+tls_advertise_hosts =
+.ifdef _HAVE_PIPE_CONNECT
+pipelining_connect_advertise_hosts =
+.endif

primary_hostname = test.ex

# ----- Main settings -----

+dmarc_tld_file = DIR/aux-fixed/TESTNUM.tldfile
+dmarc_history_file = DIR/tmp/TESTNUM.hist.dmarc
+
acl_smtp_rcpt = accept
acl_smtp_data = check_data

@@ -21,28 +33,31 @@ queue_run_in_order
begin acl

 check_data:
-  warn    !verify =    arc VALUE
-    INSERT
+  warn    !verify =    arc


   warn    logwrite =    arc_state:      <$arc_state>
     logwrite =    domains:        <$arc_domains>
     logwrite =    arc_oldest_pass <$arc_oldest_pass>
     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:} \
+    logwrite =    lh-AAR:         <$lh_ARC-Authentication-Results:>
+    logwrite =    oldest-p-AAR:   <${reduce {$lh_ARC-Authentication-Results:} \
                         {} \
                         {${if = {$arc_oldest_pass} \
                             {${extract {i}{${extract {1}{;}{$item}}}}} \
                             {$item} {$value}}} \
                     }>


-.ifdef OPTION
-  accept
-.else
-  accept add_header =    :at_start:${authresults {$primary_hostname}}
-.endif
+  require    spf =        pass : !pass
+          dmarc_status =  none : !none
+        logwrite =      dmarc_status <$dmarc_status>
+        logwrite =      dmarc_status_text <$dmarc_status_text>
+        logwrite =      dmarc_used_domain <$dmarc_used_domain>
+        logwrite =      dmarc_domain_policy <$dmarc_domain_policy>
+        set acl_m0 =    ${authresults {$primary_hostname}}
+        logwrite =      $acl_m0
+
+  accept add_header =    :at_start:$acl_m0


# ----- Routers -----

@@ -87,13 +102,7 @@ tsmtp:
   hosts =    127.0.0.1
   port =    PORT_D
   allow_localhost
-.ifndef OPTION
-.ifdef BAD
-  arc_sign =    $primary_hostname : sel : MISSING_KEY
-.else
   arc_sign =    $primary_hostname : sel : DIR/aux-fixed/dkim/dkim.private
-.endif
-.endif


 tmlist:
   driver =    smtp
@@ -101,8 +110,6 @@ tmlist:
   port =    PORT_D
   allow_localhost
   transport_filter =    /bin/cat - DIR/aux-fixed/TESTNUM.mlistfooter
-.ifndef OPTION
   arc_sign =    $primary_hostname : sel : DIR/aux-fixed/dkim/dkim.private
-.endif


 # End
diff --git a/test/log/4560 b/test/log/4560
index 40d3e5504..0f8c63aea 100644
--- a/test/log/4560
+++ b/test/log/4560
@@ -6,8 +6,8 @@
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh_A-R:         < test.ex; arc=none>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-ams:         < i=1; test.ex; arc=none>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-ams:   <i=1; test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-AAR:         < i=1; test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; arc=none>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss ARC id=qwerty1234@??? for a@???
 1999-03-02 09:44:33 Start queue run: pid=p1235
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 => a <a@???> R=d1 T=tfile
@@ -18,8 +18,8 @@
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmaY-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for za@???
 1999-03-02 09:44:33 Start queue run: pid=p1236
 1999-03-02 09:44:33 10HmaZ-000000005vi-0000 arc_state:      <pass>
@@ -27,8 +27,8 @@
 1999-03-02 09:44:33 10HmaZ-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmaZ-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmaZ-000000005vi-0000 lh_A-R:         < test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmaZ-000000005vi-0000 lh-ams:         < i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmaZ-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmaZ-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaZ-000000005vi-0000"
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 Completed
@@ -42,8 +42,8 @@
 1999-03-02 09:44:33 10HmbA-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbA-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbA-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmbA-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbA-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbA-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbA-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbA-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zza@???
 1999-03-02 09:44:33 Start queue run: pid=p1238
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 arc_state:      <pass>
@@ -51,8 +51,8 @@
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 lh_A-R:         < test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbB-000000005vi-0000 lh-ams:         < i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbB-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbB-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbB-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@???
 1999-03-02 09:44:33 10HmbA-000000005vi-0000 => za@??? <zza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbB-000000005vi-0000"
 1999-03-02 09:44:33 10HmbA-000000005vi-0000 Completed
@@ -63,8 +63,8 @@
 1999-03-02 09:44:33 10HmbC-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbC-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbC-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbC-000000005vi-0000 lh-ams:         < i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbC-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbC-000000005vi-0000 lh-AAR:         < i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbC-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbC-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbC-000000005vi-0000"
 1999-03-02 09:44:33 10HmbB-000000005vi-0000 Completed
@@ -78,8 +78,8 @@
 1999-03-02 09:44:33 10HmbD-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbD-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbD-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmbD-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbD-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbD-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbD-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbD-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zmza@???
 1999-03-02 09:44:33 Start queue run: pid=p1241
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 arc_state:      <pass>
@@ -87,8 +87,8 @@
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 lh_A-R:         < test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbE-000000005vi-0000 lh-ams:         < i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbE-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbE-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbE-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@???
 1999-03-02 09:44:33 10HmbD-000000005vi-0000 => mza@??? <zmza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbE-000000005vi-0000"
 1999-03-02 09:44:33 10HmbD-000000005vi-0000 Completed
@@ -99,8 +99,8 @@
 1999-03-02 09:44:33 10HmbF-000000005vi-0000 arc_oldest_pass <2>
 1999-03-02 09:44:33 10HmbF-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbF-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbF-000000005vi-0000 lh-ams:         < i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbF-000000005vi-0000 oldest-p-ams:   <i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1>
+1999-03-02 09:44:33 10HmbF-000000005vi-0000 lh-AAR:         < i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbF-000000005vi-0000 oldest-p-AAR:   <i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1>
 1999-03-02 09:44:33 10HmbF-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@???
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 => za@??? <mza@???> R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbF-000000005vi-0000"
 1999-03-02 09:44:33 10HmbE-000000005vi-0000 Completed
@@ -111,8 +111,8 @@
 1999-03-02 09:44:33 10HmbG-000000005vi-0000 arc_oldest_pass <2>
 1999-03-02 09:44:33 10HmbG-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbG-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=2) header.s=sel arc.oldest-pass=2 smtp.remote-ip=127.0.0.1: test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbG-000000005vi-0000 lh-ams:         < i=3; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=2) header.s=sel arc.oldest-pass=2 smtp.remote-ip=127.0.0.1: i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbG-000000005vi-0000 oldest-p-ams:   <i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1>
+1999-03-02 09:44:33 10HmbG-000000005vi-0000 lh-AAR:         < i=3; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=2) header.s=sel arc.oldest-pass=2 smtp.remote-ip=127.0.0.1: i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbG-000000005vi-0000 oldest-p-AAR:   <i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1>
 1999-03-02 09:44:33 10HmbG-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmbF-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbG-000000005vi-0000"
 1999-03-02 09:44:33 10HmbF-000000005vi-0000 Completed
@@ -126,8 +126,8 @@
 1999-03-02 09:44:33 10HmbH-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbH-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbH-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmbH-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbH-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbH-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbH-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbH-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zzmza@???
 1999-03-02 09:44:33 Start queue run: pid=p1245
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 arc_state:      <pass>
@@ -135,8 +135,8 @@
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 lh_A-R:         < test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbI-000000005vi-0000 lh-ams:         < i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbI-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbI-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbI-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for zmza@???
 1999-03-02 09:44:33 10HmbH-000000005vi-0000 => zmza@??? <zzmza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbI-000000005vi-0000"
 1999-03-02 09:44:33 10HmbH-000000005vi-0000 Completed
@@ -147,8 +147,8 @@
 1999-03-02 09:44:33 10HmbJ-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbJ-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbJ-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbJ-000000005vi-0000 lh-ams:         < i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbJ-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbJ-000000005vi-0000 lh-AAR:         < i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbJ-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbJ-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for mza@???
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 => mza@??? <zmza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbJ-000000005vi-0000"
 1999-03-02 09:44:33 10HmbI-000000005vi-0000 Completed
@@ -159,8 +159,8 @@
 1999-03-02 09:44:33 10HmbK-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbK-000000005vi-0000 reason:         <AMS body hash miscompare>
 1999-03-02 09:44:33 10HmbK-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=2) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbK-000000005vi-0000 lh-ams:         < i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbK-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbK-000000005vi-0000 lh-AAR:         < i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbK-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbK-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for za@???
 1999-03-02 09:44:33 10HmbJ-000000005vi-0000 => za@??? <mza@???> R=mlist T=tmlist H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbK-000000005vi-0000"
 1999-03-02 09:44:33 10HmbJ-000000005vi-0000 Completed
@@ -171,8 +171,8 @@
 1999-03-02 09:44:33 10HmbL-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbL-000000005vi-0000 reason:         <i=3 (cv)>
 1999-03-02 09:44:33 10HmbL-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.remote-ip=127.0.0.1: test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=2) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbL-000000005vi-0000 lh-ams:         < i=3; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.remote-ip=127.0.0.1: i=2; test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbL-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbL-000000005vi-0000 lh-AAR:         < i=3; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.remote-ip=127.0.0.1: i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbL-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbL-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@???
 1999-03-02 09:44:33 10HmbK-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbL-000000005vi-0000"
 1999-03-02 09:44:33 10HmbK-000000005vi-0000 Completed
@@ -186,8 +186,8 @@
 1999-03-02 09:44:33 10HmbM-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbM-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbM-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmbM-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbM-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbM-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbM-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbM-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zza@???
 1999-03-02 09:44:33 Start queue run: pid=p1250
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 arc_state:      <pass>
@@ -195,8 +195,8 @@
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 lh_A-R:         < test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbN-000000005vi-0000 lh-ams:         < i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbN-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbN-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbN-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for za@???
 1999-03-02 09:44:33 10HmbM-000000005vi-0000 => za@??? <zza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbN-000000005vi-0000"
 1999-03-02 09:44:33 10HmbM-000000005vi-0000 Completed
@@ -207,8 +207,8 @@
 1999-03-02 09:44:33 10HmbO-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmbO-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbO-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbO-000000005vi-0000 lh-ams:         < i=1; test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbO-000000005vi-0000 oldest-p-ams:   <i=1; test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmbO-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
+1999-03-02 09:44:33 10HmbO-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    arc=none>
 1999-03-02 09:44:33 10HmbO-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss ARC for a@???
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbO-000000005vi-0000"
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 Completed
@@ -224,8 +224,8 @@
 1999-03-02 09:44:33 10HmbP-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbP-000000005vi-0000 reason:         <AMS body hash miscompare>
 1999-03-02 09:44:33 10HmbP-000000005vi-0000 lh_A-R:         < dragon.trusteddomain.org; sender-id=fail (NotPermitted) header.sender=arc-discuss-bounces@???; spf=fail (NotPermitted) smtp.mfrom=arc-discuss-bounces@???: 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@???;\n spf=pass smtp.mfrom=jered@???>
-1999-03-02 09:44:33 10HmbP-000000005vi-0000 lh-ams:         < i=1; mailhub.convivian.com; none>
-1999-03-02 09:44:33 10HmbP-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbP-000000005vi-0000 lh-AAR:         < i=1; mailhub.convivian.com; none>
+1999-03-02 09:44:33 10HmbP-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbP-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@??? for za@???
 1999-03-02 09:44:33 Start queue run: pid=p1253
 1999-03-02 09:44:33 10HmbQ-000000005vi-0000 DKIM: d=dmarc.org s=clochette c=simple/simple a=rsa-sha256 b=1024 t=1517535263 [verification succeeded]
@@ -235,8 +235,8 @@
 1999-03-02 09:44:33 10HmbQ-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbQ-000000005vi-0000 reason:         <i=2 (cv)>
 1999-03-02 09:44:33 10HmbQ-000000005vi-0000 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.remote-ip=127.0.0.1: dragon.trusteddomain.org; sender-id=fail (NotPermitted) header.sender=arc-discuss-bounces@???; spf=fail (NotPermitted) smtp.mfrom=arc-discuss-bounces@???: 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@???;\n spf=pass smtp.mfrom=jered@???>
-1999-03-02 09:44:33 10HmbQ-000000005vi-0000 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.remote-ip=127.0.0.1: i=1; mailhub.convivian.com; none>
-1999-03-02 09:44:33 10HmbQ-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbQ-000000005vi-0000 lh-AAR:         < i=2; test.ex; smtp.remote-ip=127.0.0.1;\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.remote-ip=127.0.0.1: i=1; mailhub.convivian.com; none>
+1999-03-02 09:44:33 10HmbQ-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbQ-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss DKIM=dmarc.org id=1426665656.110316.1517535248039.JavaMail.zimbra@??? for a@???
 1999-03-02 09:44:33 10HmbP-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbQ-000000005vi-0000"
 1999-03-02 09:44:33 10HmbP-000000005vi-0000 Completed
@@ -250,8 +250,8 @@
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmbR-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbR-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbR-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbR-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for za@???
 1999-03-02 09:44:33 Start queue run: pid=p1255
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 ARC: AMS signing: privkey PEM-block import: error:1E08010C:DECODER routines::unsupported
@@ -261,8 +261,8 @@
 1999-03-02 09:44:33 10HmbS-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbS-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbS-000000005vi-0000 lh_A-R:         < test.ex;\n    arc=none>
-1999-03-02 09:44:33 10HmbS-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbS-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbS-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbS-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbS-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp S=sss for a@???
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmbS-000000005vi-0000"
 1999-03-02 09:44:33 10HmbR-000000005vi-0000 Completed
@@ -278,6 +278,6 @@
 1999-03-02 09:44:33 10HmbT-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmbT-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmbT-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmbT-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmbT-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmbT-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmbT-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmbT-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for a@???
diff --git a/test/log/4561 b/test/log/4561
index c1bdc3fac..e9bef2b90 100644
--- a/test/log/4561
+++ b/test/log/4561
@@ -6,8 +6,8 @@
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 reason:         <(sequence; expected i=1)>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh_A-R:         < test.ex;\n     iprev=fail;\n     auth=pass (PLAIN) smtp.auth=fred@???>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-ams:         < i=2; test.ex;\n     iprev=fail;\n     auth=pass (PLAIN) smtp.auth=fred@???>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-AAR:         < i=2; test.ex;\n     iprev=fail;\n     auth=pass (PLAIN) smtp.auth=fred@???>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss id=3885245d-3bae-66a2-7a1e-0dbceae2fb50@??? for a@???
 1999-03-02 09:44:33 Start queue run: pid=p1235
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 => a <a@???> R=d1 T=tfile
diff --git a/test/log/4562 b/test/log/4562
index 0df43e55b..0c7cb7a74 100644
--- a/test/log/4562
+++ b/test/log/4562
@@ -6,16 +6,16 @@
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh_A-R:         < test.ex; arc=none>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-ams:         < i=1; test.ex; arc=none>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-ams:   <i=1; test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-AAR:         < i=1; test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; arc=none>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= has_arc@??? H=(xxx) [127.0.0.1] P=smtp S=sss ARC id=qwerty1234@??? for a@???
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 arc_state:      <none>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 domains:        <>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 arc_oldest_pass <1>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 reason:         <>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh_A-R:         <>
-1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh-ams:         <>
-1999-03-02 09:44:33 10HmaY-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmaY-000000005vi-0000 <= no_arc@??? H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@??? for a@???
 1999-03-02 09:44:33 Start queue run: pid=p1235
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 => a <a@???> R=d1 T=tfile
diff --git a/test/log/4563 b/test/log/4563
index efbbcf588..3b578d517 100644
--- a/test/log/4563
+++ b/test/log/4563
@@ -6,8 +6,8 @@
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 arc_oldest_pass <0>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 reason:         <AMS sig nonverify>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh_A-R:         < test.ex; arc=none>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-ams:         < i=2; test.ex; arc=none: i=1; test.ex; arc=none>
-1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-ams:   <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-AAR:         < i=2; test.ex; arc=none: i=1; test.ex; arc=none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-AAR:   <>
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss id=qwerty1234@??? for a@???
 1999-03-02 09:44:33 Start queue run: pid=p1235
 1999-03-02 09:44:33 10HmaX-000000005vi-0000 => a <a@???> R=d1 T=tfile
diff --git a/test/log/4690 b/test/log/4690
new file mode 100644
index 000000000..44b3b8958
--- /dev/null
+++ b/test/log/4690
@@ -0,0 +1,57 @@
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=p1234, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 arc_state:      <none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 domains:        <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 arc_oldest_pass <0>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 reason:         <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh_A-R:         <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 lh-AAR:         <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 oldest-p-AAR:   <>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 DMARC results: spf_domain=test.ex dmarc_domain=test.ex spf_align=yes dkim_align=no enforcement='Accept'
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_status <accept>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_status_text <Accept>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_used_domain <test.ex>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 dmarc_domain_policy <none>
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 Authentication-Results: test.ex;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 <= CALLER@??? H=(xxx) [127.0.0.1] P=smtp S=sss for zza@???
+1999-03-02 09:44:33 Start queue run: pid=p1235
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 arc_state:      <pass>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 domains:        <test.ex>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 reason:         <>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh_A-R:         < test.ex;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 lh-AAR:         < i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 DMARC results: spf_domain=test.ex dmarc_domain=test.ex spf_align=yes dkim_align=no enforcement='Accept'
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_status <accept>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_status_text <Accept>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_used_domain <test.ex>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 dmarc_domain_policy <none>
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 Authentication-Results: test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp K S=sss ARC for za@???
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 => za@??? <zza@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] K C="250- 1nn byte chunk, total 1nn\\n250 OK id=10HmaY-000000005vi-0000"
+1999-03-02 09:44:33 10HmaX-000000005vi-0000 Completed
+1999-03-02 09:44:33 End queue run: pid=p1235
+1999-03-02 09:44:33 Start queue run: pid=p1236
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 arc_state:      <pass>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 domains:        <test.ex:test.ex>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 arc_oldest_pass <1>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 reason:         <>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 lh_A-R:         < test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: test.ex;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 lh-AAR:         < i=2; test.ex; smtp.remote-ip=127.0.0.1;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1: i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 oldest-p-AAR:   <i=1; test.ex; smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=none>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 DMARC results: spf_domain=test.ex dmarc_domain=test.ex spf_align=yes dkim_align=no enforcement='Accept'
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 dmarc_status <accept>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 dmarc_status_text <Accept>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 dmarc_used_domain <test.ex>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 dmarc_domain_policy <none>
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 Authentication-Results: test.ex;\n    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;\n    spf=pass smtp.mailfrom=test.ex;\n    dmarc=pass header.from=test.ex;\n    arc=pass (i=2) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 <= CALLER@??? H=localhost (test.ex) [127.0.0.1] P=esmtp K S=sss ARC for a@???
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 => a@??? <za@???> R=fwd T=tsmtp H=127.0.0.1 [127.0.0.1] K C="250- 2nn byte chunk, total 2nn\\n250 OK id=10HmaZ-000000005vi-0000"
+1999-03-02 09:44:33 10HmaY-000000005vi-0000 Completed
+1999-03-02 09:44:33 End queue run: pid=p1236
+1999-03-02 09:44:33 Start queue run: pid=p1237
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 => a <a@???> R=d1 T=tfile
+1999-03-02 09:44:33 10HmaZ-000000005vi-0000 Completed
+1999-03-02 09:44:33 End queue run: pid=p1237
diff --git a/test/mail/4560.a b/test/mail/4560.a
index 4d904278e..234a54e5a 100644
--- a/test/mail/4560.a
+++ b/test/mail/4560.a
@@ -38,10 +38,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for a@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
-     b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72
-      AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC
-      s8DrtRVB3Tt8T/4g8L2SRY0=;
-ARC-Authentication-Results: i=1; test.ex;
+     b=1WIsU9bnj5eAXJuTBjQIEmuhuzJcPtBUJhL1FgyJ6baycKwrLLyIssyx/6Viio6BqaH6+ga2YW
+      kMzlYwiSMAo1GB4HgFSkk2hsFggtL6pSTO7pf3h+mi2Id+wuzQP+Pkp+ZD3xRkpmFqHtrP1eK5
+      2L21YoWFRum8v5bAKk7ps4c=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
     arc=none
 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
     bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
@@ -72,10 +72,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for a@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel;
-     b=gQvDl2aKy+MEWgwP9A31sLHf4b6zOSwZhglgBrO2apeKFIRv54YTKVe44/6D0iJurZM8mjndMy
-      u78sFMRrBb6zm99rUiEg48TDqIXOCJkSBpArs2liF34HdzpCsJxMgIIhxxNyVzjGGQdQCvSxm6
-      e7tMbokkI+KFMnpG+G1Xjyk=;
-ARC-Authentication-Results: i=2; test.ex;
+     b=BpKMUfv872xyyd+0dF631GElxk0jmXuzhSEZmT+zlTIHm53RB3NfqXDsy31ffk75CQ5YhIDKaw
+      iCrfHDbwcuRG63Bud2mdfUuWhKXbREGj9aSVSs8D+Z2irv7D6T5zX1Dym6leEL71206FzSJxHw
+      TiwYO2xg+T16cWizyX4WleY=;
+ARC-Authentication-Results: i=2; test.ex; smtp.remote-ip=127.0.0.1;
     iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
     arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
@@ -94,10 +94,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for za@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
-     b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72
-      AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC
-      s8DrtRVB3Tt8T/4g8L2SRY0=;
-ARC-Authentication-Results: i=1; test.ex;
+     b=1WIsU9bnj5eAXJuTBjQIEmuhuzJcPtBUJhL1FgyJ6baycKwrLLyIssyx/6Viio6BqaH6+ga2YW
+      kMzlYwiSMAo1GB4HgFSkk2hsFggtL6pSTO7pf3h+mi2Id+wuzQP+Pkp+ZD3xRkpmFqHtrP1eK5
+      2L21YoWFRum8v5bAKk7ps4c=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
     arc=none
 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
     bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
@@ -128,10 +128,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for a@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=3; cv=pass; a=rsa-sha256; d=test.ex; s=sel;
-     b=advgCcXZhwJFZi5rzQgnThsSOX6MsCpnXWxyub3UbuQI5RonZOw7SwEVJ2j4Q32z1d54wws1/c
-      2MJeB2ChZUy+J0rNrXLEWsZZtOrQDx1fEaGL7sXC8RYshnkboBiN8lbkuoZHUZWPILKIWd5V2M
-      pN4yMCO6kQ0wyOoUj8JousQ=;
-ARC-Authentication-Results: i=3; test.ex;
+     b=hcSl2rS19q1ophE/sNVZCnh/EBmCmHBEO0dI1uBYqbPzigyn4dYTbFYvwTU7P5aLZQqDMsE8L+
+      paNdS8Txw+cUbyDPAvOre2s+4Iu7oDGpNWgvitZypVoQNz47insbdbsGHZwu7ZTFpDTMZMDxG9
+      LGNvssRFO2C3itM/nDLSzQI=;
+ARC-Authentication-Results: i=3; test.ex; smtp.remote-ip=127.0.0.1;
     iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
     arc=pass (i=2) header.s=sel arc.oldest-pass=2 smtp.remote-ip=127.0.0.1
 ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
@@ -150,10 +150,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for za@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel;
-     b=odwQlZ9ZCMTWG30i3IPycNo+3kLWIngjWVJKGF8d8CfNEIEeK7ao89Wy9bPEwcnXHYN2HnDjtL
-      UXPiuo0BLPS4UCAvVdBd1Kr/rUHfoIysIFF6OggChI2ZeUqRlkD1GRV7C5LACsDrGR+HQQzXPI
-      ugidXguiQVpY4mMgc3Kbr44=;
-ARC-Authentication-Results: i=2; test.ex;
+     b=lVYxYNg6L8tVWRCfCyZQdcaxGW2cdzFWrU6Rn9d2jruRA9DOPWGZ8i4lgwvGdYv2QxNpo6Dt/5
+      jjC7eTljtPJQnVPsZ7CkAfwwHP8FUlAbigmuEo6N4sKtqmdEBv6Cic75pMdPMYhEhtmrsCIBdk
+      xzogtv2CL/8F8gq+tS1oz04=;
+ARC-Authentication-Results: i=2; test.ex; smtp.remote-ip=127.0.0.1;
     iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
     arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
@@ -172,10 +172,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for mza@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
-     b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72
-      AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC
-      s8DrtRVB3Tt8T/4g8L2SRY0=;
-ARC-Authentication-Results: i=1; test.ex;
+     b=1WIsU9bnj5eAXJuTBjQIEmuhuzJcPtBUJhL1FgyJ6baycKwrLLyIssyx/6Viio6BqaH6+ga2YW
+      kMzlYwiSMAo1GB4HgFSkk2hsFggtL6pSTO7pf3h+mi2Id+wuzQP+Pkp+ZD3xRkpmFqHtrP1eK5
+      2L21YoWFRum8v5bAKk7ps4c=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
     arc=none
 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
     bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
@@ -210,10 +210,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for a@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=3; cv=fail; a=rsa-sha256; d=test.ex; s=sel;
-     b=SwyS6CAxe1WUpQ6/gjhehp05c2J3qn5TgqiEzNZENLQ0LmoFesan/Hs/WUXsu68TWbk12zSYGl
-      j8SymB40wpTVbyI0nB9X3f/EV35apVdZCCbb7fhDcItiaveQAYAQjupnD1Gzf7bvkFnHUNIyvc
-      mBRUsVzafYLyWHjoPimb0QE=;
-ARC-Authentication-Results: i=3; test.ex;
+     b=rgKTK6kS5MHWCA/3GsZJkj+tEbi0PKJ0r+zE13V7CR5HlhRlIW4byAQOBR5uBlpjIXzpGOYJvb
+      WUvyoqSi1QBr8e6aA53OOY8M9uG49uVnkvgErIkf4IXRSpTfmkR/lfkoznA30QSg/UpD31A/OS
+      IWHm1Bvex7ptXoh7qkcDMWo=;
+ARC-Authentication-Results: i=3; test.ex; smtp.remote-ip=127.0.0.1;
     iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
     arc=fail (i=2)(AMS body hash miscompare) header.s=sel arc.oldest-pass=0 smtp.remote-ip=127.0.0.1
 ARC-Message-Signature: i=3; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
@@ -241,10 +241,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for mza@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel;
-     b=gQvDl2aKy+MEWgwP9A31sLHf4b6zOSwZhglgBrO2apeKFIRv54YTKVe44/6D0iJurZM8mjndMy
-      u78sFMRrBb6zm99rUiEg48TDqIXOCJkSBpArs2liF34HdzpCsJxMgIIhxxNyVzjGGQdQCvSxm6
-      e7tMbokkI+KFMnpG+G1Xjyk=;
-ARC-Authentication-Results: i=2; test.ex;
+     b=BpKMUfv872xyyd+0dF631GElxk0jmXuzhSEZmT+zlTIHm53RB3NfqXDsy31ffk75CQ5YhIDKaw
+      iCrfHDbwcuRG63Bud2mdfUuWhKXbREGj9aSVSs8D+Z2irv7D6T5zX1Dym6leEL71206FzSJxHw
+      TiwYO2xg+T16cWizyX4WleY=;
+ARC-Authentication-Results: i=2; test.ex; smtp.remote-ip=127.0.0.1;
     iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
     arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
 ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
@@ -263,10 +263,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for zmza@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
-     b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72
-      AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC
-      s8DrtRVB3Tt8T/4g8L2SRY0=;
-ARC-Authentication-Results: i=1; test.ex;
+     b=1WIsU9bnj5eAXJuTBjQIEmuhuzJcPtBUJhL1FgyJ6baycKwrLLyIssyx/6Viio6BqaH6+ga2YW
+      kMzlYwiSMAo1GB4HgFSkk2hsFggtL6pSTO7pf3h+mi2Id+wuzQP+Pkp+ZD3xRkpmFqHtrP1eK5
+      2L21YoWFRum8v5bAKk7ps4c=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
     arc=none
 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
     bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
@@ -310,10 +310,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for za@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
-     b=DaGjkoR0m1B7KxZMbkzZFTviDSdrEf+VX4N7wo/f6PCDHEnt3fiIg646KrbgQHZQG23rVlPm72
-      AaJMBhVpewKjPtdc/7fNY3Kgyp4ttwug8jMEGYU1cgaJjkx3Xp/HMk52b3HVnPvV900YNrmfGC
-      s8DrtRVB3Tt8T/4g8L2SRY0=;
-ARC-Authentication-Results: i=1; test.ex;
+     b=1WIsU9bnj5eAXJuTBjQIEmuhuzJcPtBUJhL1FgyJ6baycKwrLLyIssyx/6Viio6BqaH6+ga2YW
+      kMzlYwiSMAo1GB4HgFSkk2hsFggtL6pSTO7pf3h+mi2Id+wuzQP+Pkp+ZD3xRkpmFqHtrP1eK5
+      2L21YoWFRum8v5bAKk7ps4c=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
     arc=none
 ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
     bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
@@ -347,10 +347,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for a@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=2; cv=fail; a=rsa-sha256; d=test.ex; s=sel;
-     b=e1ldkzDyxJIvQd+ZOylCkekKOj3WVUZiptsJYuoiM0tsBRoiHA5O6RDwrNzCQxRWT05PzW3GBy
-      Dkiejo2w30n9QBueQH4h8BvCl/QMlmmdaIy02ZKqfvtp1hxR125TREXdigK9ULQZF4rIrDma5S
-      hpd7e9cat3tVvL+aDVT6qBc=;
-ARC-Authentication-Results: i=2; test.ex;
+     b=Arb1wGCte7UUR5c0p37zQ18YW3/X5St95wIStSACUHtWn8IRCaFfb6DJ9j7VnnJznmhjhYKcg3
+      5L+Sf/VOYHi2z67eoMXZ6ZB1J3giqmNLD6MqllLaXsH3yqdmO9SRG19KBh56ZG8HILgNgw3hkC
+      wJ1OUmg359gm9hk3qYXIgvY=;
+ARC-Authentication-Results: i=2; test.ex; smtp.remote-ip=127.0.0.1;
     dkim=pass header.d=dmarc.org header.s=clochette header.a=rsa-sha256;
     dkim=fail (body hash mismatch; body probably modified in transit)
          header.d=convivian.com header.s=default header.a=rsa-sha256;
diff --git a/test/mail/4565.a b/test/mail/4565.a
index 6be8edafe..10cb76c81 100644
--- a/test/mail/4565.a
+++ b/test/mail/4565.a
@@ -12,10 +12,10 @@ Received: from localhost ([127.0.0.1] helo=test.ex)
     for a@???;
     Tue, 2 Mar 1999 09:44:33 +0000
 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
-     b=1J94ImExSjtnwHY/c/aN3BX/xlnQfi6CPdGQvbeSdsbCCEtOqK9547tA54tYFh8beeVECAR0xu
-      9fCSAjZ/0WM7mrxKNMbWkoHNoejUhNkcxJOtFmiS/0JKPQGk8HTE7FHLbogUQvEJoVBBnqo6xW
-      nFtzlI3JfLnWvB3FQ316xLs=;
-ARC-Authentication-Results: i=1; test.ex;
+     b=guJqF/mOsuUjSLbdDSMvwf13qMVw2TPUmUhp37HWgIFppyAwBueoEQ+tqaxZBhqw54W9TiHA8o
+      JTsfWJemHwDWiP4BI9ccdeiWrpAIxb2QfL09oybcs6sQHMTvYsWItmuWQlMMsGMqTtrNdi1E+B
+      WHu89huK0FxZOBBJpj634IQ=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
     dkim=fail (body hash mismatch; body probably modified in transit)
          header.d=example.com header.s=sel header.a=rsa-sha256;
     arc=none
diff --git a/test/mail/4690.a b/test/mail/4690.a
new file mode 100644
index 000000000..b9d2a1a09
--- /dev/null
+++ b/test/mail/4690.a
@@ -0,0 +1,67 @@
+From CALLER@??? Tue Mar 02 09:44:33 1999
+Authentication-Results: test.ex;
+    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
+    spf=pass smtp.mailfrom=test.ex;
+    dmarc=pass header.from=test.ex;
+    arc=pass (i=2) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
+Received: from localhost ([127.0.0.1] helo=test.ex)
+    by test.ex with esmtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaZ-000000005vi-0000
+    for a@???;
+    Tue, 2 Mar 1999 09:44:33 +0000
+ARC-Seal: i=2; cv=pass; a=rsa-sha256; d=test.ex; s=sel;
+     b=OzDYecPkQoqA16q0dDASO39Eay+pylGCs/4RiR5an1lw1fq7Lu8u6yhnzLySkR777csWnaGebP
+      HA5SYBIQ0eSWFbMbs5B2dR5APaUIfu4Vvsvrlj9IWyNwI9TdTbrQsePy4dnd8WFNXLiiHTL7GJ
+      cdm3SxO7jJM0MFe3MEvqCu4=;
+ARC-Authentication-Results: i=2; test.ex; smtp.remote-ip=127.0.0.1;
+    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
+    spf=pass smtp.mailfrom=test.ex;
+    dmarc=pass header.from=test.ex;
+    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
+ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
+    bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
+    h=From:Subject;
+    b=vvajkPsGZ5v5OVCvDnPGZeCGtjCkLVOICQqFbbeUGPbeULu0YuzvDyEtSae2eWhbCLyJK6eCbN
+      sRKBMkuZHH+Q5Drlx5xAFcIJqzdj9Vpfx3Wy/Rif1yKGiwzlQ8rtuf6eF7rWseDjjLR2vww2GS
+      dqUNp6aMd8hfWPpXaJ1RIac=;
+Authentication-Results: test.ex;
+    iprev=pass (localhost) smtp.remote-ip=127.0.0.1;
+    spf=pass smtp.mailfrom=test.ex;
+    dmarc=pass header.from=test.ex;
+    arc=pass (i=1) header.s=sel arc.oldest-pass=1 smtp.remote-ip=127.0.0.1
+Received: from localhost ([127.0.0.1] helo=test.ex)
+    by test.ex with esmtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaY-000000005vi-0000
+    for za@???;
+    Tue, 2 Mar 1999 09:44:33 +0000
+ARC-Seal: i=1; cv=none; a=rsa-sha256; d=test.ex; s=sel;
+     b=lEmC1Nc2r9oPcx4h0WxPXzfnw6j0o1F1Ok25rtKz4O6A2Kv9TSOqqtytBlbxJ+mCeGK93ZTJyl
+      8dRzO3iXk1xLW4n12vMe+Y2ufQp7HspPW2xRcyXJJlQnX//8QSRXHoBapPxQd2f2KgXXS2HICx
+      LiXcuLE9Jbs4mPpb9uPV4RQ=;
+ARC-Authentication-Results: i=1; test.ex; smtp.remote-ip=127.0.0.1;
+    spf=pass smtp.mailfrom=test.ex;
+    dmarc=pass header.from=test.ex;
+    arc=none
+ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=test.ex; s=sel;
+    bh=HUzfKKxIjPIa07lkj5uzDQ3q5YTRF/NwAUE7dhrrfvs=;
+    h=From:Subject;
+    b=HnYnwHbI6HGBLhgfnLys5BL7OjZqwyA7xEBRukSPv/mcJHgeNcmmVhxB7hue4/6+bD47uM27Gl
+      5qmC0zTGx26326+FEfDBAbZutxECSEZEdg8dhI8bZdO0fNvAD2tO6D+lG0XzqXMKg9woCQX1DV
+      uqlAsrZssxQT8tAc6MnXaP0=;
+Authentication-Results: test.ex;
+    spf=pass smtp.mailfrom=test.ex;
+    dmarc=pass header.from=test.ex;
+    arc=none
+Received: from [127.0.0.1] (helo=xxx)
+    by test.ex with smtp (Exim x.yz)
+    (envelope-from <CALLER@???>)
+    id 10HmaX-000000005vi-0000
+    for zza@???;
+    Tue, 2 Mar 1999 09:44:33 +0000
+Subject: Test
+From: <CALLER@???>
+
+This is a test body.
+
diff --git a/test/scripts/4500-DKIM/4500 b/test/scripts/4500-DKIM/4500
index 2d1f2f35e..d1cc646f9 100644
--- a/test/scripts/4500-DKIM/4500
+++ b/test/scripts/4500-DKIM/4500
@@ -7,7 +7,7 @@ exim -DSERVER=server -DMSIZE='rsa=512 ed25519=250' -bd -oX PORT_D
 #  - sha1, 1024b
 # Mail original in aux-fixed/4500.msg1.txt
 # Sig generated by: perl aux-fixed/dkim/sign.pl --method=simple/simple < aux-fixed/4500.msg1.txt
-# NB: simpla canon does not affect tabs-vs-spaces in header continuation lines, which
+# NB: simple canon does not affect tabs-vs-spaces in header continuation lines, which
 # likely matters in the DKIM sig header.  Take care!
 client 127.0.0.1 PORT_D
 ??? 220
diff --git a/test/scripts/4690-DMARC-ARC/4690 b/test/scripts/4690-DMARC-ARC/4690
new file mode 100644
index 000000000..18210785a
--- /dev/null
+++ b/test/scripts/4690-DMARC-ARC/4690
@@ -0,0 +1,45 @@
+# DMARC history-report of ARC results
+#
+mkdir DIR/tmp
+sudo chmod 777 DIR/tmp
+#
+exim -DSERVER=server -bd -oX PORT_D
+****
+#
+# We send this one through two forwarding hops.
+# It starts off bare, so the 1st forwarder reception gets an ARC status of "none".
+# The outbound signs it with that, and the 2nd forwarder is happy to pass it.
+# The outbound signs again, and the final receiver is happy.
+#
+client 127.0.0.1 PORT_D
+??? 220
+HELO xxx
+??? 250
+MAIL FROM:<CALLER@???>
+??? 250
+RCPT TO:<zza@???>
+??? 250
+DATA
+??? 354
+Subject: Test
+From: <CALLER@???>
+
+This is a test body.
+.
+??? 250
+QUIT
+??? 221
+****
+#
+exim -DSERVER=server -DNOTDAEMON -q
+****
+exim -DSERVER=server -DNOTDAEMON -q
+****
+exim -DSERVER=server -DNOTDAEMON -q
+****
+#
+killdaemon
+cat DIR/tmp/TESTNUM.hist.dmarc
+#
+sudo rm -fr DIR/tmp
+no_msglog_check
diff --git a/test/scripts/4690-DMARC-ARC/REQUIRES b/test/scripts/4690-DMARC-ARC/REQUIRES
new file mode 100644
index 000000000..9d8d25739
--- /dev/null
+++ b/test/scripts/4690-DMARC-ARC/REQUIRES
@@ -0,0 +1,3 @@
+support DMARC
+support DKIM
+support Experimental_ARC
diff --git a/test/stdout/4650 b/test/stdout/4650
index 1afe0217c..4da1909c6 100644
--- a/test/stdout/4650
+++ b/test/stdout/4650
@@ -67,6 +67,8 @@ sp 0
 align_dkim 5
 align_spf 5
 action 2
+arc 11
+arc_policy $d json:[]
 job 10HmaY-000000005vi-0000
 reporter myhost.test.ex
 received 1692480217
@@ -86,3 +88,5 @@ sp 0
 align_dkim 4
 align_spf 5
 action 2
+arc 11
+arc_policy $d json:[]
diff --git a/test/stdout/4690 b/test/stdout/4690
new file mode 100644
index 000000000..e76a46806
--- /dev/null
+++ b/test/stdout/4690
@@ -0,0 +1,86 @@
+Connecting to 127.0.0.1 port 1225 ... connected
+??? 220
+<<< 220 test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
+>>> HELO xxx
+??? 250
+<<< 250 test.ex Hello xxx [127.0.0.1]
+>>> MAIL FROM:<CALLER@???>
+??? 250
+<<< 250 OK
+>>> RCPT TO:<zza@???>
+??? 250
+<<< 250 Accepted
+>>> DATA
+??? 354
+<<< 354 Enter message, ending with "." on a line by itself
+>>> Subject: Test
+>>> From: <CALLER@???>
+>>> 
+>>> This is a test body.
+>>> .
+??? 250
+<<< 250 OK id=10HmaX-000000005vi-0000
+>>> QUIT
+??? 221
+<<< 221 test.ex closing connection
+End of script
+job 10HmaX-000000005vi-0000
+reporter test.ex
+received 1692480217
+ipaddr 127.0.0.1
+from test.ex
+mfrom test.ex
+spf 0
+pdomain test.ex
+policy 15
+rua -
+pct 100
+adkim 114
+aspf 114
+p 110
+sp 0
+align_dkim 5
+align_spf 4
+action 2
+arc 11
+arc_policy 1 json[ ]
+job 10HmaY-000000005vi-0000
+reporter test.ex
+received 1692480217
+ipaddr 127.0.0.1
+from test.ex
+mfrom test.ex
+spf 0
+pdomain test.ex
+policy 15
+rua -
+pct 100
+adkim 114
+aspf 114
+p 110
+sp 0
+align_dkim 5
+align_spf 4
+action 2
+arc 0
+arc_policy 0 json[ ("i":1, "d":"test.ex", "s":"sel", "ip":"127.0.0.1") ]
+job 10HmaZ-000000005vi-0000
+reporter test.ex
+received 1692480217
+ipaddr 127.0.0.1
+from test.ex
+mfrom test.ex
+spf 0
+pdomain test.ex
+policy 15
+rua -
+pct 100
+adkim 114
+aspf 114
+p 110
+sp 0
+align_dkim 5
+align_spf 4
+action 2
+arc 0
+arc_policy 0 json[ ("i":1, "d":"test.ex", "s":"sel", "ip":"127.0.0.1"), ("i":2, "d":"test.ex", "s":"sel", "ip":"127.0.0.1") ]


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/