You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by fk...@apache.org on 2026/03/24 20:24:04 UTC
svn commit: r1932516 - in spamassassin/trunk: lib/Mail/SpamAssassin/Plugin rules
Author: fkento
Date: Tue Mar 24 20:24:04 2026
New Revision: 1932516
Log:
Handle DMARC permerror/temperror without falling back to Mail::DMARC::PurePerl
When an Authentication-Results header contains dmarc=permerror or
dmarc=temperror, these are terminal results that should not trigger a
fallback to Mail::DMARC::PurePerl for a redundant DNS lookup.
Also fixes the Mail::DMARC::PurePerl path where "too many policies"
was incorrectly setting dmarc_policy to "no policy available", which
caused check_dmarc_missing to fire instead of the more accurate
permerror result.
Adds new check_dmarc_permerror and check_dmarc_temperror eval rules
with corresponding DMARC_PERMERROR and DMARC_TEMPERROR rules.
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm
spamassassin/trunk/rules/25_dmarc.cf
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm Tue Mar 24 20:10:31 2026 (r1932515)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DMARC.pm Tue Mar 24 20:24:04 2026 (r1932516)
@@ -50,6 +50,16 @@ Mail::SpamAssassin::Plugin::DMARC - chec
describe DMARC_MISSING Missing DMARC policy
tflags DMARC_MISSING net
score DMARC_MISSING 0.001
+
+ header DMARC_PERMERROR eval:check_dmarc_permerror()
+ describe DMARC_PERMERROR DMARC permanent error
+ tflags DMARC_PERMERROR net
+ score DMARC_PERMERROR 0.001
+
+ header DMARC_TEMPERROR eval:check_dmarc_temperror()
+ describe DMARC_TEMPERROR DMARC temporary error
+ tflags DMARC_TEMPERROR net
+ score DMARC_TEMPERROR 0.001
endif
=head1 DESCRIPTION
@@ -97,6 +107,8 @@ sub new {
$self->register_eval_rule("check_dmarc_quarantine", $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS);
$self->register_eval_rule("check_dmarc_none", $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS);
$self->register_eval_rule("check_dmarc_missing", $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS);
+ $self->register_eval_rule("check_dmarc_permerror", $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS);
+ $self->register_eval_rule("check_dmarc_temperror", $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS);
return $self;
}
@@ -217,6 +229,28 @@ sub check_dmarc_missing {
return $self->_check_eval($pms, $result);
}
+sub check_dmarc_permerror {
+ my ($self, $pms, $name) = @_;
+
+ my $result = sub {
+ defined $pms->{dmarc_result} &&
+ $pms->{dmarc_result} eq 'permerror';
+ };
+
+ return $self->_check_eval($pms, $result);
+}
+
+sub check_dmarc_temperror {
+ my ($self, $pms, $name) = @_;
+
+ my $result = sub {
+ defined $pms->{dmarc_result} &&
+ $pms->{dmarc_result} eq 'temperror';
+ };
+
+ return $self->_check_eval($pms, $result);
+}
+
sub check_tick {
my ($self, $opts) = @_;
@@ -368,8 +402,9 @@ sub _check_dmarc {
} elsif (defined $pms->{dmarc_result}) {
if (defined $result->reason->[0]{comment} &&
$result->reason->[0]{comment} eq 'too many policies') {
- dbg("result: no policy available (too many policies)");
- $pms->{dmarc_policy} = 'no policy available';
+ dbg("result: permerror (too many policies)");
+ $pms->{dmarc_result} = 'permerror';
+ $pms->{dmarc_policy} = 'permerror';
} elsif ($result->result eq 'pass') {
dbg("result: pass");
my $policy = eval { $result->published->p };
@@ -410,6 +445,12 @@ sub _check_dmarc_authres {
if ($result eq 'none') {
# dmarc=none means no DMARC record published, no policy to look up
$policy = 'no policy available';
+ } elsif ($result eq 'permerror' || $result eq 'temperror') {
+ # error results are terminal, no point in falling back to local check
+ $pms->{dmarc_result} = $result;
+ $pms->{dmarc_policy} = $result;
+ dbg("using Authentication-Results: result=%s", $result);
+ return 1;
} else {
# Try to get policy from A-R header properties
foreach my $parsed (@{$pms->{authres_parsed}{dmarc} || []}) {
Modified: spamassassin/trunk/rules/25_dmarc.cf
==============================================================================
--- spamassassin/trunk/rules/25_dmarc.cf Tue Mar 24 20:10:31 2026 (r1932515)
+++ spamassassin/trunk/rules/25_dmarc.cf Tue Mar 24 20:24:04 2026 (r1932516)
@@ -58,5 +58,17 @@ priority DMARC_MISSING 500
tflags DMARC_MISSING net
reuse DMARC_MISSING
+header DMARC_PERMERROR eval:check_dmarc_permerror()
+describe DMARC_PERMERROR DMARC permanent error
+priority DMARC_PERMERROR 500
+tflags DMARC_PERMERROR net
+reuse DMARC_PERMERROR
+
+header DMARC_TEMPERROR eval:check_dmarc_temperror()
+describe DMARC_TEMPERROR DMARC temporary error
+priority DMARC_TEMPERROR 500
+tflags DMARC_TEMPERROR net
+reuse DMARC_TEMPERROR
+
endif