-/* 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. */
-
-int dmarc_process() {
- int sr, origin; /* used in SPF section */
- int dmarc_spf_result = 0; /* stores spf into dmarc conn ctx */
- pdkim_signature *sig = NULL;
- BOOL has_dmarc_record = TRUE;
- u_char **ruf; /* forensic report addressees, if called for */
-
- /* ACLs have "control=dmarc_disable_verify" */
- if (dmarc_disable_verify == TRUE)
+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)
+ {
+ uschar *record = string_copyn_taint(US rr->data, rr->size, GET_TAINTED);
+ store_free_dns_answer(dnsa);
+ return record;
+ }
+store_free_dns_answer(dnsa);
+return NULL;
+}
+
+
+static int
+dmarc_write_history_file()
+{
+int history_file_fd;
+ssize_t written_len;
+int tmp_ans;
+u_char **rua; /* aggregate report addressees */
+uschar *history_buffer = NULL;
+
+if (!dmarc_history_file)