they may be empty; requires that headers_remove items with embedded
colons must have them doubled (or the list-separator changed).
+TL/07 Add new dmarc expansion variable $dmarc_domain_policy to directly
+ view the policy declared in the DMARC record. Currently, $dmarc_status
+ is a combined value of both the record presence and the result of the
+ analysis.
Exim version 4.82
-----------------
Of course, you can also use any other lookup method that Exim
supports, including LDAP, Postgres, MySQL, etc, as long as the
-result is a list of colon-separated strings;
+result is a list of colon-separated strings.
Several expansion variables are set before the DATA ACL is
processed, and you can use them in this ACL. The following
o $dmarc_status
This is a one word status indicating what the DMARC library
- thinks of the email.
+ thinks of the email. It is a combination of the results of
+ DMARC record lookup and the SPF/DKIM/DMARC processing results
+ (if a DMARC record was found). The actual policy declared
+ in the DMARC record is in a separate expansion variable.
o $dmarc_status_text
This is a slightly longer, human readable status.
This is the domain which DMARC used to look up the DMARC
policy record.
+ o $dmarc_domain_policy
+ This is the policy declared in the DMARC record. Valid values
+ are "none", "reject" and "quarantine". It is blank when there
+ is any error, including no DMARC record.
+
o $dmarc_ar_header
This is the entire Authentication-Results header which you can
add using an add_header modifier.
warn !domains = +screwed_up_dmarc_records
control = dmarc_enable_forensic
+ warn condition = (lookup if destined to mailing list)
+ set acl_m_mailing_list = 1
+
(DATA ACL)
warn dmarc_status = accept : none : off
!authenticated = *
set $acl_m_quarantine = 1
# Do something in a transport with this flag variable
+ deny condition = ${if eq{$dmarc_domain_policy}{reject}}
+ condition = ${if eq{$acl_m_mailing_list}{1}}
+ message = Messages from $dmarc_used_domain break mailing lists
+
deny dmarc_status = reject
!authenticated = *
message = Message from $domain_used_domain failed sender's DMARC policy, REJECT
int history_file_status = DMARC_HIST_OK;
uschar *dkim_history_buffer= NULL;
+typedef struct dmarc_exim_p {
+ uschar *name;
+ int value;
+} dmarc_exim_p;
+
+static dmarc_exim_p dmarc_policy_description[] = {
+ { US"", DMARC_RECORD_P_UNSPECIFIED },
+ { US"none", DMARC_RECORD_P_NONE },
+ { US"quarantine", DMARC_RECORD_P_QUARANTINE },
+ { US"reject", DMARC_RECORD_P_REJECT },
+ { NULL, 0 }
+};
/* Accept an error_block struct, initialize if empty, parse to the
* end, and append the two strings passed to it. Used for adding
* variable amounts of value:pair data to the forensic emails. */
int dmarc_process() {
int sr, origin; /* used in SPF section */
int dmarc_spf_result = 0; /* stores spf into dmarc conn ctx */
+ int tmp_ans, c;
pdkim_signature *sig = NULL;
BOOL has_dmarc_record = TRUE;
u_char **ruf; /* forensic report addressees, if called for */
has_dmarc_record = FALSE;
break;
}
+
+ /* 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 != NULL; c++) {
+ if (tmp_ans == dmarc_policy_description[c].value) {
+ dmarc_domain_policy = string_sprintf("%s",dmarc_policy_description[c].name);
+ break;
+ }
+ }
+
/* Can't use exim's string manipulation functions so allocate memory
* for libopendmarc using its max hostname length definition. */
uschar *dmarc_domain = (uschar *)calloc(DMARC_MAXHOSTNAMELEN, sizeof(uschar));
#endif
#ifdef EXPERIMENTAL_DMARC
{ "dmarc_ar_header", vtype_stringptr, &dmarc_ar_header },
+ { "dmarc_domain_policy", vtype_stringptr, &dmarc_domain_policy },
{ "dmarc_status", vtype_stringptr, &dmarc_status },
{ "dmarc_status_text", vtype_stringptr, &dmarc_status_text },
{ "dmarc_used_domain", vtype_stringptr, &dmarc_used_domain },
#ifdef EXPERIMENTAL_DMARC
BOOL dmarc_has_been_checked = FALSE;
uschar *dmarc_ar_header = NULL;
+uschar *dmarc_domain_policy = NULL;
uschar *dmarc_forensic_sender = NULL;
uschar *dmarc_history_file = NULL;
uschar *dmarc_status = NULL;
#ifdef EXPERIMENTAL_DMARC
extern BOOL dmarc_has_been_checked; /* Global variable to check if test has been called yet */
extern uschar *dmarc_ar_header; /* Expansion variable, suggested header for dmarc auth results */
+extern uschar *dmarc_domain_policy; /* Expansion for declared policy of used domain */
extern uschar *dmarc_forensic_sender; /* Set sender address for forensic reports */
extern uschar *dmarc_history_file; /* Expansion variable, file to store dmarc results */
extern uschar *dmarc_status; /* Expansion variable, one word value */