Files
dependabot[bot]andKrzysztof Zając 781c8e95bf Bump checkdmarc from 5.17.5 to 6.0.1 in /scan (#257)
Bumps [checkdmarc](https://github.com/domainaware/checkdmarc) from
5.17.5 to 6.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/domainaware/checkdmarc/releases">checkdmarc's
releases</a>.</em></p>
<blockquote>
<h2>6.0.0</h2>
<p>An RFC conformance audit compared every module line-by-line against
its
governing specification (SPF: RFC 7208; DMARC: RFC 9989/9990; TLSRPT:
RFC 8460; MTA-STS: RFC 8461; SMTP/MX: RFC 5321/7505/2181; DNSSEC:
RFC 4033-4035; SOA: RFC 1035/2181; BIMI: draft-brand-indicators-14) and
found 81 discrepancies, most confirmed by executing the old code. This
release fixes all of them. Many fixes change validation verdicts —
records the specs call valid are no longer rejected, and records they
call invalid are no longer accepted — hence the major version.
This release also contains everything staged for 5.18.0, which
was never released.</p>
<h3>Breaking changes</h3>
<ul>
<li>MX STARTTLS/TLS testing is now opt-in: pass
<code>--check-mx-tls</code> on the CLI or <code>check_mx_tls=True</code>
to <code>check_domains()</code>, <code>check_mx()</code>, or
<code>get_mx_hosts()</code>. The <code>--skip-tls</code> flag and
<code>skip_tls</code> parameter are still accepted but do nothing, and
passing <code>skip_tls</code> emits a <code>DeprecationWarning</code>.
As a result, MX host results no longer carry the <code>tls</code> and
<code>starttls</code> keys, and the CSV
<code>tls</code>/<code>starttls</code> columns are empty, unless TLS
testing is turned on</li>
<li><code>check_dnssec()</code> performs a real chain-of-trust check
anchored at the parent zone's DS record instead of verifying a zone's
DNSKEY against itself. A zone with no DS at its parent (including
&quot;island of security&quot; zones) is insecure per RFC 4033 §4.3 and
returns <code>False</code>; a broken zone such as dnssec-failed.org
returns <code>False</code> through any resolver, where it previously
returned <code>True</code> through non-validating resolvers. Bogus
(SERVFAIL with DS present) is now warned about distinctly from
unsigned</li>
<li>Unknown and extension tags/fields now parse with a warning instead
of failing validation, as each spec requires: SPF unknown modifiers (RFC
7208 §6), DMARC unknown tags (RFC 9989 §4.7), TLSRPT extension fields
(RFC 8460 §3), MTA-STS extension fields and policy keys (RFC 8461 §3.2),
and BIMI unknown tags (draft §4.3). An unknown field is ignored only
when it fits the spec's own extension grammar; a malformed extension
name or value still fails the record or policy</li>
<li>A TXT record unrelated to the record type being queried is now
discarded instead of failing validation, per each spec's discard rule:
TLSRPT (RFC 8460 §3.1), MTA-STS (RFC 8461 §3.1), BIMI (draft §7.2), and
DMARC report authorization records (RFC 9990 §4). Each query also now
returns the record carrying the version tag rather than whichever TXT
record the resolver listed first. When a real record sits beside the
unrelated one, the unrelated record is reported as a warning; when it is
the only record present, the check reports that no record exists. DMARC
authorization records are discarded silently, and a wildcard
authorization record that is unrelated is still an error. Callers
catching <code>UnrelatedTXTRecordFoundAtTLSRPT</code> or
<code>UnrelatedTXTRecordFoundAtBIMI</code> should note that those
queries now raise <code>SMTPTLSReportingRecordNotFound</code> and
<code>BIMIRecordNotFound</code> instead</li>
<li>Records the old code wrongly accepted are now invalid: SPF records
exceeding the 10-DNS-lookup limit through <code>a</code>,
<code>ptr</code>, or macro-valued terms (RFC 7208 §4.6.4 — the limit was
previously only enforced for some mechanism types), SPF
<code>include</code> of a domain with no SPF record (permerror per RFC
7208 §5.2), MTA-STS policies missing a required key (RFC 8461 §3.2 — the
check was dead code), BIMI records missing the required <code>l=</code>
tag (draft §4.3), lowercase <code>v=dmarc1</code> (RFC 9989 §4.8), and
an SPF qualifier on a modifier or a value on the <code>all</code>
mechanism (RFC 7208 §12)</li>
<li>MTA-STS and TLSRPT records are now matched case-sensitively, with no
whitespace allowed around the version tag's <code>=</code>, because RFC
8461 §3.1 and RFC 8460 §3 spell those literals with the case-sensitive
<code>%s</code> notation of RFC 7405. Records such as <code>V=STSv1;
id=…</code>, <code>v = STSv1; id=…</code>, <code>v=STSv1; ID=…</code>,
and <code>v=TLSRPTv1; RUA=…</code> parsed before and are now syntax
errors. DMARC is unaffected: RFC 9989 §4.8 makes its tag names
case-insensitive and allows whitespace around <code>=</code>, which this
release starts honoring</li>
<li>The DMARC tree walk now applies RFC 9989 §4.10.2 Organizational
Domain selection (<code>psd=n</code> wins; a <code>psd=y</code> record
hands off to the record one label below it, warning when none is
published there; otherwise the record with the fewest labels applies)
instead of stopping at the closest parent record, which selected the
opposite policy in the RFC's own worked example</li>
</ul>
<h3>Added</h3>
<ul>
<li><code>--check-mx-tls</code> CLI flag and <code>check_mx_tls</code>
API parameter (see breaking changes)</li>
<li><code>get_mx_record_set()</code> in <code>checkdmarc.utils</code>,
returning MX hosts, warnings, null MX status, and the number of MX
records in the answer (the new <code>MXRecordSet</code> type), parsed
from dnspython rdata instead of text splitting. The record count is what
separates &quot;no MX records at all&quot; from &quot;MX records that
produced no usable host&quot;</li>
<li>Null MX (RFC 7505) handling: a lone <code>0 .</code> record yields
an explicit &quot;does not accept mail&quot; warning distinct from
having no MX records (which now notes the RFC 5321 §5.1 implicit MX
rule); a null MX coexisting with other MX records is flagged as an RFC
7505 §3 violation instead of producing an empty-hostname host entry; a
root (<code>.</code>) target with a non-zero preference, such as
<code>10 .</code>, is warned about as malformed instead of becoming an
empty-hostname host entry</li>
<li>MX target sanity warnings: IP-address literals (RFC 5321 §5.1),
hostnames failing RFC 5321 §2.3.5 label syntax, and targets that are
CNAME aliases (RFC 2181 §10.3)</li>
<li>DNS over HTTPS (DoH) and DNS over TLS (DoT) support through the
existing <code>nameservers</code> option, matching parsedmarc
([parsedmarc PR <a
href="https://redirect.github.com/domainaware/checkdmarc/issues/886">#886</a>](<a
href="https://redirect.github.com/domainaware/parsedmarc/pull/886">domainaware/parsedmarc#886</a>)).
Each entry picks its own transport: an IP address means plain DNS on
port 53 exactly as before, an <code>https://</code> URL means DoH, and
<code>tls://ip[:port][#hostname]</code> means DoT, where the port
defaults to 853 and the optional <code>#hostname</code> names the
server's TLS certificate identity, matching systemd-resolved's syntax.
DoH queries go through a shared <code>httpx</code> client that honors
the
<code>HTTP_PROXY</code>/<code>HTTPS_PROXY</code>/<code>NO_PROXY</code>
and <code>SSL_CERT_FILE</code>/<code>SSL_CERT_DIR</code> environment
variables, so checks can run on networks that block outbound DNS but
provide an HTTP proxy. The DNSSEC, DNSKEY, and TLSA checks use the
configured transports too. The <code>dnspython</code> requirement is now
<code>dnspython[doh]&gt;=2.7.0</code>, and <code>httpx&gt;=0.26.0</code>
is a new direct dependency for the shared DoH client</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Update the GitHub Actions used by the workflows to their latest
major versions: <code>checkout</code> v7, <code>setup-python</code> v7,
<code>codecov-action</code> v7, <code>upload-artifact</code> v7,
<code>download-artifact</code> v8, <code>configure-pages</code> v6,
<code>upload-pages-artifact</code> v5, and <code>deploy-pages</code> v5.
Most now run on Node.js 24 (<code>upload-pages-artifact</code> and
<code>codecov-action</code> are composite actions). The deprecated
<code>codecov/test-results-action</code> is replaced by
<code>codecov/codecov-action@v7</code> with <code>report_type:
test_results</code>, which is the same upload it performed before; no
other workflow behavior changes</li>
<li>Renamed identifiers whose names misdescribed what they hold, keeping
the old names as deprecated aliases where they were public API:
<ul>
<li><code>checkdmarc.dnssec.check_dnssec()</code> replaces
<code>test_dnssec()</code>, matching every other module's
<code>check_*()</code> entry point; <code>test_dnssec()</code> remains
as a deprecated alias that warns</li>
<li><code>get_mx_hosts()</code> takes
<code>approved_mx_hostnames</code>, matching <code>check_mx()</code> and
<code>check_domains()</code>; the old <code>approved_hostnames</code>
keyword remains as a deprecated alias that warns</li>
<li>The CLI accepts <code>--nameservers</code> as an alias for
<code>-n/--nameserver</code>, and
<code>--approved-ns</code>/<code>--approved-mx</code> as clearer aliases
for <code>--ns</code>/<code>--mx</code></li>
<li><code>MTASTSQueryResult</code>, <code>MTASTSCheckResult</code>,
<code>SMTPTLSReportingQueryResult</code>, and
<code>SMTPTLSReportingResult</code> replace their plural forms, matching
the singular BIMI result types; the plural names remain as aliases</li>
<li><code>MTA_STS_TAGS</code> and <code>SMTP_TLS_REPORTING_TAGS</code>
replace the lowercase <code>mta_sts_tags</code> and
<code>smtp_rpt_tags</code> constants, matching <code>BIMI_TAGS</code>;
the lowercase names remain as aliases</li>
</ul>
</li>
<li>The <code>MXHost</code> type now declares the fields MX host dicts
actually carry (<code>addresses</code>, <code>dnssec</code>,
<code>tlsa</code>, <code>tls</code>, <code>starttls</code> as optional
keys, with <code>hostname</code> and <code>preference</code> required in
a new <code>MXRecord</code> base); the declared
<code>ip_addresses</code> field never existed in any produced data</li>
<li>Removed unused module-level copies of the DMARC grammar internals
(<code>checkdmarc.dmarc.version_tag</code>, <code>tag_value</code>, and
<code>START</code>), which duplicated the private grammar class and
shadow-collided with unrelated locals</li>
<li>Many internal variables renamed so a name no longer changes type or
meaning mid-function (split results, parse results, pyleri grammar
results, joined display strings); no behavior changes</li>
</ul>
<h3>Removed</h3>
<ul>
<li>The <code>pyopenssl</code> dependency, as planned in 5.17.5.
checkdmarc stopped importing pyOpenSSL in that release; the floor was
kept for one release only so upgrades would also move any leftover
pyOpenSSL to a version compatible with <code>cryptography</code> 50</li>
</ul>
<h3>Fixed</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/domainaware/checkdmarc/blob/main/CHANGELOG.md">checkdmarc's
changelog</a>.</em></p>
<blockquote>
<h2>6.0.0</h2>
<p>An RFC conformance audit compared every module line-by-line against
its
governing specification (SPF: RFC 7208; DMARC: RFC 9989/9990; TLSRPT:
RFC 8460; MTA-STS: RFC 8461; SMTP/MX: RFC 5321/7505/2181; DNSSEC:
RFC 4033-4035; SOA: RFC 1035/2181; BIMI: draft-brand-indicators-14) and
found 81 discrepancies, most confirmed by executing the old code. This
release fixes all of them. Many fixes change validation verdicts —
records the specs call valid are no longer rejected, and records they
call invalid are no longer accepted — hence the major version.
This release also contains everything staged for 5.18.0, which
was never released.</p>
<h3>Breaking changes</h3>
<ul>
<li>MX STARTTLS/TLS testing is now opt-in: pass
<code>--check-mx-tls</code> on the CLI or <code>check_mx_tls=True</code>
to <code>check_domains()</code>, <code>check_mx()</code>, or
<code>get_mx_hosts()</code>. The <code>--skip-tls</code> flag and
<code>skip_tls</code> parameter are still accepted but do nothing, and
passing <code>skip_tls</code> emits a <code>DeprecationWarning</code>.
As a result, MX host results no longer carry the <code>tls</code> and
<code>starttls</code> keys, and the CSV
<code>tls</code>/<code>starttls</code> columns are empty, unless TLS
testing is turned on</li>
<li><code>check_dnssec()</code> performs a real chain-of-trust check
anchored at the parent zone's DS record instead of verifying a zone's
DNSKEY against itself. A zone with no DS at its parent (including
&quot;island of security&quot; zones) is insecure per RFC 4033 §4.3 and
returns <code>False</code>; a broken zone such as dnssec-failed.org
returns <code>False</code> through any resolver, where it previously
returned <code>True</code> through non-validating resolvers. Bogus
(SERVFAIL with DS present) is now warned about distinctly from
unsigned</li>
<li>Unknown and extension tags/fields now parse with a warning instead
of failing validation, as each spec requires: SPF unknown modifiers (RFC
7208 §6), DMARC unknown tags (RFC 9989 §4.7), TLSRPT extension fields
(RFC 8460 §3), MTA-STS extension fields and policy keys (RFC 8461 §3.2),
and BIMI unknown tags (draft §4.3). An unknown field is ignored only
when it fits the spec's own extension grammar; a malformed extension
name or value still fails the record or policy</li>
<li>A TXT record unrelated to the record type being queried is now
discarded instead of failing validation, per each spec's discard rule:
TLSRPT (RFC 8460 §3.1), MTA-STS (RFC 8461 §3.1), BIMI (draft §7.2), and
DMARC report authorization records (RFC 9990 §4). Each query also now
returns the record carrying the version tag rather than whichever TXT
record the resolver listed first. When a real record sits beside the
unrelated one, the unrelated record is reported as a warning; when it is
the only record present, the check reports that no record exists. DMARC
authorization records are discarded silently, and a wildcard
authorization record that is unrelated is still an error. Callers
catching <code>UnrelatedTXTRecordFoundAtTLSRPT</code> or
<code>UnrelatedTXTRecordFoundAtBIMI</code> should note that those
queries now raise <code>SMTPTLSReportingRecordNotFound</code> and
<code>BIMIRecordNotFound</code> instead</li>
<li>Records the old code wrongly accepted are now invalid: SPF records
exceeding the 10-DNS-lookup limit through <code>a</code>,
<code>ptr</code>, or macro-valued terms (RFC 7208 §4.6.4 — the limit was
previously only enforced for some mechanism types), SPF
<code>include</code> of a domain with no SPF record (permerror per RFC
7208 §5.2), MTA-STS policies missing a required key (RFC 8461 §3.2 — the
check was dead code), BIMI records missing the required <code>l=</code>
tag (draft §4.3), lowercase <code>v=dmarc1</code> (RFC 9989 §4.8), and
an SPF qualifier on a modifier or a value on the <code>all</code>
mechanism (RFC 7208 §12)</li>
<li>MTA-STS and TLSRPT records are now matched case-sensitively, with no
whitespace allowed around the version tag's <code>=</code>, because RFC
8461 §3.1 and RFC 8460 §3 spell those literals with the case-sensitive
<code>%s</code> notation of RFC 7405. Records such as <code>V=STSv1;
id=…</code>, <code>v = STSv1; id=…</code>, <code>v=STSv1; ID=…</code>,
and <code>v=TLSRPTv1; RUA=…</code> parsed before and are now syntax
errors. DMARC is unaffected: RFC 9989 §4.8 makes its tag names
case-insensitive and allows whitespace around <code>=</code>, which this
release starts honoring</li>
<li>The DMARC tree walk now applies RFC 9989 §4.10.2 Organizational
Domain selection (<code>psd=n</code> wins; a <code>psd=y</code> record
hands off to the record one label below it, warning when none is
published there; otherwise the record with the fewest labels applies)
instead of stopping at the closest parent record, which selected the
opposite policy in the RFC's own worked example</li>
</ul>
<h3>Added</h3>
<ul>
<li><code>--check-mx-tls</code> CLI flag and <code>check_mx_tls</code>
API parameter (see breaking changes)</li>
<li><code>get_mx_record_set()</code> in <code>checkdmarc.utils</code>,
returning MX hosts, warnings, null MX status, and the number of MX
records in the answer (the new <code>MXRecordSet</code> type), parsed
from dnspython rdata instead of text splitting. The record count is what
separates &quot;no MX records at all&quot; from &quot;MX records that
produced no usable host&quot;</li>
<li>Null MX (RFC 7505) handling: a lone <code>0 .</code> record yields
an explicit &quot;does not accept mail&quot; warning distinct from
having no MX records (which now notes the RFC 5321 §5.1 implicit MX
rule); a null MX coexisting with other MX records is flagged as an RFC
7505 §3 violation instead of producing an empty-hostname host entry; a
root (<code>.</code>) target with a non-zero preference, such as
<code>10 .</code>, is warned about as malformed instead of becoming an
empty-hostname host entry</li>
<li>MX target sanity warnings: IP-address literals (RFC 5321 §5.1),
hostnames failing RFC 5321 §2.3.5 label syntax, and targets that are
CNAME aliases (RFC 2181 §10.3)</li>
<li>DNS over HTTPS (DoH) and DNS over TLS (DoT) support through the
existing <code>nameservers</code> option, matching parsedmarc
([parsedmarc PR <a
href="https://redirect.github.com/domainaware/checkdmarc/issues/886">#886</a>](<a
href="https://redirect.github.com/domainaware/parsedmarc/pull/886">domainaware/parsedmarc#886</a>)).
Each entry picks its own transport: an IP address means plain DNS on
port 53 exactly as before, an <code>https://</code> URL means DoH, and
<code>tls://ip[:port][#hostname]</code> means DoT, where the port
defaults to 853 and the optional <code>#hostname</code> names the
server's TLS certificate identity, matching systemd-resolved's syntax.
DoH queries go through a shared <code>httpx</code> client that honors
the
<code>HTTP_PROXY</code>/<code>HTTPS_PROXY</code>/<code>NO_PROXY</code>
and <code>SSL_CERT_FILE</code>/<code>SSL_CERT_DIR</code> environment
variables, so checks can run on networks that block outbound DNS but
provide an HTTP proxy. The DNSSEC, DNSKEY, and TLSA checks use the
configured transports too. The <code>dnspython</code> requirement is now
<code>dnspython[doh]&gt;=2.7.0</code>, and <code>httpx&gt;=0.26.0</code>
is a new direct dependency for the shared DoH client</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Update the GitHub Actions used by the workflows to their latest
major versions: <code>checkout</code> v7, <code>setup-python</code> v7,
<code>codecov-action</code> v7, <code>upload-artifact</code> v7,
<code>download-artifact</code> v8, <code>configure-pages</code> v6,
<code>upload-pages-artifact</code> v5, and <code>deploy-pages</code> v5.
Most now run on Node.js 24 (<code>upload-pages-artifact</code> and
<code>codecov-action</code> are composite actions). The deprecated
<code>codecov/test-results-action</code> is replaced by
<code>codecov/codecov-action@v7</code> with <code>report_type:
test_results</code>, which is the same upload it performed before; no
other workflow behavior changes</li>
<li>Renamed identifiers whose names misdescribed what they hold, keeping
the old names as deprecated aliases where they were public API:
<ul>
<li><code>checkdmarc.dnssec.check_dnssec()</code> replaces
<code>test_dnssec()</code>, matching every other module's
<code>check_*()</code> entry point; <code>test_dnssec()</code> remains
as a deprecated alias that warns</li>
<li><code>get_mx_hosts()</code> takes
<code>approved_mx_hostnames</code>, matching <code>check_mx()</code> and
<code>check_domains()</code>; the old <code>approved_hostnames</code>
keyword remains as a deprecated alias that warns</li>
<li>The CLI accepts <code>--nameservers</code> as an alias for
<code>-n/--nameserver</code>, and
<code>--approved-ns</code>/<code>--approved-mx</code> as clearer aliases
for <code>--ns</code>/<code>--mx</code></li>
<li><code>MTASTSQueryResult</code>, <code>MTASTSCheckResult</code>,
<code>SMTPTLSReportingQueryResult</code>, and
<code>SMTPTLSReportingResult</code> replace their plural forms, matching
the singular BIMI result types; the plural names remain as aliases</li>
<li><code>MTA_STS_TAGS</code> and <code>SMTP_TLS_REPORTING_TAGS</code>
replace the lowercase <code>mta_sts_tags</code> and
<code>smtp_rpt_tags</code> constants, matching <code>BIMI_TAGS</code>;
the lowercase names remain as aliases</li>
</ul>
</li>
<li>The <code>MXHost</code> type now declares the fields MX host dicts
actually carry (<code>addresses</code>, <code>dnssec</code>,
<code>tlsa</code>, <code>tls</code>, <code>starttls</code> as optional
keys, with <code>hostname</code> and <code>preference</code> required in
a new <code>MXRecord</code> base); the declared
<code>ip_addresses</code> field never existed in any produced data</li>
<li>Removed unused module-level copies of the DMARC grammar internals
(<code>checkdmarc.dmarc.version_tag</code>, <code>tag_value</code>, and
<code>START</code>), which duplicated the private grammar class and
shadow-collided with unrelated locals</li>
<li>Many internal variables renamed so a name no longer changes type or
meaning mid-function (split results, parse results, pyleri grammar
results, joined display strings); no behavior changes</li>
</ul>
<h3>Removed</h3>
<ul>
<li>The <code>pyopenssl</code> dependency, as planned in 5.17.5.
checkdmarc stopped importing pyOpenSSL in that release; the floor was
kept for one release only so upgrades would also move any leftover
pyOpenSSL to a version compatible with <code>cryptography</code> 50</li>
</ul>
<h3>Fixed</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/domainaware/checkdmarc/commit/237b1a728b0f0885b12dbc24142106c6c43405f5"><code>237b1a7</code></a>
Fix RFC conformance across all modules; make MX TLS testing opt-in
(6.0.0) (#...</li>
<li><a
href="https://github.com/domainaware/checkdmarc/commit/11acda945c5164839250f7aa76512216760d2775"><code>11acda9</code></a>
Release 5.18.0: encrypted DNS (DoH/DoT), documentation overhaul, and bug
fixe...</li>
<li><a
href="https://github.com/domainaware/checkdmarc/commit/d4866ca25b092790667aae2c595ef1e4375077d8"><code>d4866ca</code></a>
Update GitHub Actions to their latest major versions (<a
href="https://redirect.github.com/domainaware/checkdmarc/issues/271">#271</a>)</li>
<li><a
href="https://github.com/domainaware/checkdmarc/commit/d45ad01e15c369e08508dd078ff518ea622001c3"><code>d45ad01</code></a>
Upload test results via codecov-action@v5 (<a
href="https://redirect.github.com/domainaware/checkdmarc/issues/270">#270</a>)</li>
<li>See full diff in <a
href="https://github.com/domainaware/checkdmarc/compare/5.17.5...6.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=checkdmarc&package-manager=pip&previous-version=5.17.5&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Krzysztof Zając <krzysztof.zajac@cert.pl>
2026-09-07 09:06:01 +02:00

95 lines
4.6 KiB
Python

import re
from base import BaseTestCase
from config import TEST_DOMAIN
CONFIG_WITH_WARNINGS_REGEX = r"DMARC:\s*configuration warnings"
INCORRECT_CONFIG_REGEX = r"DMARC:\s*incorrect configuration"
CORRECT_CONFIG_REGEX = r"DMARC:\s*correct configuration"
WARNING_REGEX = "bi bi-exclamation-triangle"
class DMARCTestCase(BaseTestCase):
def test_correct(self) -> None:
result = self.check_domain("correct.dmarc." + TEST_DOMAIN)
assert re.search(CORRECT_CONFIG_REGEX, result)
assert not re.search(INCORRECT_CONFIG_REGEX, result)
def test_starts_with_whitespace(self) -> None:
result = self.check_domain("starts-with-whitespace.dmarc." + TEST_DOMAIN)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert re.search(INCORRECT_CONFIG_REGEX, result)
assert (
"Found a DMARC record that starts with whitespace. Please remove the whitespace, as some "
"implementations may not process it correctly."
) in result
def test_none_policy(self) -> None:
result = self.check_domain("none-policy.dmarc." + TEST_DOMAIN)
assert re.search(CONFIG_WITH_WARNINGS_REGEX, result)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert not re.search(INCORRECT_CONFIG_REGEX, result)
assert "A p tag value of none makes DMARC unenforced on email sent as" in result
def test_unrelated_records(self) -> None:
result = self.check_domain("contains-unrelated-records.dmarc." + TEST_DOMAIN)
assert re.search(CONFIG_WITH_WARNINGS_REGEX, result)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert not re.search(INCORRECT_CONFIG_REGEX, result)
assert (
"Unrelated TXT record found in the &#39;_dmarc&#39; subdomain. We recommend removing it, as such unrelated "
"records may cause problems with some DMARC implementations."
) in result
def test_public_suffix(self) -> None:
result = self.check_domain("gov.pl")
assert (
"Requested to scan a domain that is a public suffix, i.e. a domain such as .com where anybody could "
"register their subdomain. Such domain don&#39;t have to have properly configured e-mail sender verification "
"mechanisms. Please make sure you really wanted to check such domain and not its subdomain."
) in result
def test_syntax_error(self) -> None:
result = self.check_domain("syntax-error.dmarc." + TEST_DOMAIN)
assert re.search(INCORRECT_CONFIG_REGEX, result)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert (
"Error: Expected end_of_statement or tag_value at position 10 (marked with ➞) in: v=DMARC1; ➞=none"
) in result or (
"Error: Expected tag_value or end_of_statement at position 10 (marked with ➞) in: v=DMARC1; ➞=none"
) in result
def test_syntax_error_policy_location(self) -> None:
result = self.check_domain("syntax-error-policy-location.dmarc." + TEST_DOMAIN)
assert re.search(WARNING_REGEX, result)
assert ("The p tag does not immediately follow the v tag.") in result
def test_rua_no_mailto(self) -> None:
result = self.check_domain("rua-no-mailto.dmarc." + TEST_DOMAIN)
assert re.search(INCORRECT_CONFIG_REGEX, result)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert (
"dmarc@mailgoose.cert.pl is not a valid DMARC report URI - please make sure that the URI begins "
"with a scheme such as mailto:"
) in result
def test_rua_double_mailto(self) -> None:
result = self.check_domain("rua-double-mailto.dmarc." + TEST_DOMAIN)
assert re.search(INCORRECT_CONFIG_REGEX, result)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert "mailto:mailto:dmarc@mailgoose.cert.pl is not a valid DMARC report URI" in result
assert "please make sure that the URI begins with a schema:" not in result
def test_no_rua_policy_none(self) -> None:
result = self.check_domain("no-rua-none.dmarc." + TEST_DOMAIN)
assert re.search(INCORRECT_CONFIG_REGEX, result)
assert not re.search(CORRECT_CONFIG_REGEX, result)
assert "A p tag value of none makes DMARC unenforced on email sent as" in result
def test_no_rua_policy_reject(self) -> None:
result = self.check_domain("no-rua-reject.dmarc." + TEST_DOMAIN)
assert not re.search(INCORRECT_CONFIG_REGEX, result)
assert not re.search(WARNING_REGEX, result)
assert "rua tag" not in result
assert re.search(CORRECT_CONFIG_REGEX, result)