+int
+dmarc_store_data(header_line *hdr)
+{
+/* No debug output because would change every test debug output */
+if (!f.dmarc_disable_verify)
+ from_header = hdr;
+return OK;
+}
+
+
+static void
+dmarc_send_forensic_report(u_char **ruf)
+{
+uschar *recipient, *save_sender;
+BOOL send_status = FALSE;
+error_block *eblock = NULL;
+FILE *message_file = NULL;
+
+/* Earlier ACL does not have *required* control=dmarc_enable_forensic */
+if (!f.dmarc_enable_forensic)
+ return;
+
+if ( dmarc_policy == DMARC_POLICY_REJECT && action == DMARC_RESULT_REJECT
+ || dmarc_policy == DMARC_POLICY_QUARANTINE && action == DMARC_RESULT_QUARANTINE
+ || dmarc_policy == DMARC_POLICY_NONE && action == DMARC_RESULT_REJECT
+ || dmarc_policy == DMARC_POLICY_NONE && action == DMARC_RESULT_QUARANTINE
+ )
+ if (ruf)
+ {
+ eblock = add_to_eblock(eblock, US"Sender Domain", dmarc_used_domain);
+ eblock = add_to_eblock(eblock, US"Sender IP Address", sender_host_address);
+ eblock = add_to_eblock(eblock, US"Received Date", tod_stamp(tod_full));
+ eblock = add_to_eblock(eblock, US"SPF Alignment",
+ sa == DMARC_POLICY_SPF_ALIGNMENT_PASS ? US"yes" : US"no");
+ eblock = add_to_eblock(eblock, US"DKIM Alignment",
+ da == DMARC_POLICY_DKIM_ALIGNMENT_PASS ? US"yes" : US"no");
+ eblock = add_to_eblock(eblock, US"DMARC Results", dmarc_status_text);
+
+ for (int c = 0; ruf[c]; c++)
+ {
+ recipient = string_copylc(ruf[c]);
+ if (Ustrncmp(recipient, "mailto:",7))
+ continue;
+ /* Move to first character past the colon */
+ recipient += 7;
+ DEBUG(D_receive)
+ debug_printf("DMARC forensic report to %s%s\n", recipient,
+ (host_checking || f.running_in_test_harness) ? " (not really)" : "");
+ if (host_checking || f.running_in_test_harness)
+ continue;
+
+ if (!moan_send_message(recipient, ERRMESS_DMARC_FORENSIC, eblock,
+ header_list, message_file, NULL))
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "failure to send DMARC forensic report to %s", recipient);
+ }
+ }
+}
+
+
+/* Look up a DNS dmarc record for the given domain. Return it or NULL */
+
+static uschar *
+dmarc_dns_lookup(uschar * dom)
+{
+dns_answer * dnsa = store_get_dns_answer();
+dns_scan dnss;
+int rc = dns_lookup(dnsa, string_sprintf("_dmarc.%s", dom), T_TXT, NULL);
+
+if (rc == DNS_SUCCEED)
+ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+ rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
+ if (rr->type == T_TXT && rr->size > 3)
+ return string_copyn(US rr->data, rr->size);
+return NULL;