Skip to content

Releases: domainaware/checkdmarc

5.15.4

07 May 02:05
8229622

Choose a tag to compare

Fixes

  • Stop reporting jurisdictionOfIncorporationStateOrProvinceName /
    jurisdictionOfIncorporationLocalityName as required when both are absent.
    Per VMC Requirements §7.1.4.2.2(j), entities incorporated at the country
    level (e.g. bbc.co.uk) MUST include only jurisdictionCountryName
    state/province and locality MUST NOT be present. The same correction
    applies to the parallel statute* fields for Government Marks
    (§7.1.4.2.2(s)). The locality-level form is still validated:
    jurisdictionOfIncorporationLocalityName (and statuteLocalityName)
    now imply that their state/province counterpart must also be present
    (#242).
  • Deduplicate the bidirectional "either A or B" error so the
    localityName / stateOrProvinceName rule is reported once instead
    of twice when both fields are absent.

Changes

  • Warn when a BIMI SVG <title> element is a generator/template
    placeholder (e.g. bimi-svg-tiny-12-ps, Untitled). The title should
    be a descriptive name for the brand or mark.
  • Document that BIMI mark certificates are validated against the
    AuthIndicators Working Group's
    Minimum Security Requirements for Issuance of Mark Certificates.

5.15.3

02 May 21:22

Choose a tag to compare

Fixes

  • Display a warning is a BIMI image is provided without a VMC/CMC

5.15.2

23 Apr 02:53
55cbf7b

Choose a tag to compare

Changes

  • Cap the per-query UDP timeout at min(1.0, timeout) for single-nameserver
    configurations as well as multi-nameserver ones. Previously, when only one
    nameserver was configured (or the system default list had a single entry),
    resolver.timeout and resolver.lifetime were both set to the full
    timeout budget, which collapses dnspython's UDP retry loop to a single
    attempt — a single dropped UDP datagram then consumed the whole lifetime
    and raised LifetimeTimeout, while dig (which defaults to +tries=3)
    would mask the same blip by retrying. dnspython now retries UDP within
    the lifetime window (~2 attempts at the default 2s budget), matching
    dig's behavior in spirit and eliminating spurious single-NS timeouts
    on paths with occasional packet loss.

5.15.1

23 Apr 02:21
4311a9b

Choose a tag to compare

Changes

  • Revert the 5.15.0 default of auto-configuring public nameservers
    (1.1.1.1, 8.8.8.8) when no nameservers are passed. When nameservers
    is None, checkdmarc now falls back to the system-configured resolvers
    again (/etc/resolv.conf on Linux/macOS, the OS resolver on Windows),
    matching the 5.14.x and earlier behavior. The auto-configured default would
    surprise users running split-horizon or internal DNS and broke workflows
    that previously relied on the system resolver.
  • Rename the exposed constant from DEFAULT_DNS_NAMESERVERS to
    RECOMMENDED_DNS_NAMESERVERS to reflect that it is an opt-in
    recommendation, not an automatic default. It is re-exported from the
    package root as checkdmarc.RECOMMENDED_DNS_NAMESERVERS so callers can
    easily opt in with
    check_domains(..., nameservers=RECOMMENDED_DNS_NAMESERVERS).
  • Documentation now calls out mixing public resolvers from different
    providers as a best practice for public-internet checks.

5.15.0

22 Apr 20:55
9015116

Choose a tag to compare

Changes (breaking)

  • Rename the timeout_retries kwarg to retries across all public APIs, and
    rename the CLI flag --timeout-retries to --retries. The retry logic now
    covers transient failures beyond timeouts — dns.resolver.LifetimeTimeout,
    dns.resolver.NoNameservers (typically a SERVFAIL from upstream), and
    OSError during TCP fallback. NXDOMAIN and NoAnswer remain
    non-retryable (definitive negative answers).
  • Change the default retry count from 2 to 0. The retry loop tripled
    worst-case query time without helping when stalls were caused by
    misbehaving authoritative nameservers. Callers that want retries can pass
    retries=2 or use --retries 2 on the CLI.
  • Cap the per-nameserver query budget at min(1.0, timeout) seconds, with
    an overall lifetime = timeout * len(nameservers). When multiple
    nameservers are configured, dnspython now falls through to the next one
    after at most 1s instead of letting a single slow or broken nameserver
    consume the whole lifetime before any fallback is attempted. Failover
    across the configured list happens inside each attempt; retries retries
    the whole attempt after all configured nameservers have been tried.
  • Default to a mix of public DNS providers (1.1.1.1, 8.8.8.8) when no
    nameservers are passed, instead of falling back to /etc/resolv.conf.
    Combined with the per-nameserver cap above, this gives cross-provider
    failover out of the box — a slow or broken path at one resolver falls
    through to the other within ~1s. Exposed as
    checkdmarc._constants.DEFAULT_DNS_NAMESERVERS. Users that need
    system-configured or internal resolvers can still pass them explicitly
    via nameservers=... or --nameserver.
  • Centralize default timeouts and retry counts as constants in
    checkdmarc._constants (DEFAULT_DNS_TIMEOUT, DEFAULT_DNS_MAX_RETRIES,
    DEFAULT_SMTP_TIMEOUT), matching the existing DEFAULT_HTTP_TIMEOUT
    pattern. Function defaults now reference these constants so tuning is a
    one-file change.

5.14.3

21 Apr 15:45

Choose a tag to compare

Fixes

  • Fix type of approved_mx_hostnames parameter in check_domains (closes #238)
  • Resolve Pyright/Pylance type errors and warnings across the project:
    • Use Literal[True]/Literal[False] for valid in DMARCResults /
      DMARCErrorResults to enable discriminated union narrowing
    • Make nameservers parameter Optional in check_mx, get_mx_hosts, and
      get_tlsa_records to match call sites and the underlying query_dns
    • Type get_nameservers return as NameserverResultOk; type the error path
      in check_ns as NameserverResultError
    • Type parsed_dmarc_record in parse_bimi_record / check_bimi as
      Optional[Union[DMARCResults, DMARCErrorResults]]
    • Type results_to_json, results_to_csv, and results_to_csv_rows inputs
      as DomainCheckResult | list[DomainCheckResult]
    • Remove stray tuple wrapper around an add_argument call in the CLI

5.14.2

05 Apr 02:10

Choose a tag to compare

Fixes

  • Fix unclosed socket ResourceWarning in test_tls and test_starttls by
    using SMTP context managers and replacing timeout-decorator with smtplib's
    built-in timeout parameter
  • Remove timeout-decorator dependency

5.13.4

18 Feb 19:00

Choose a tag to compare

Improvements

  • More lax SPF record verification for parked domains. (PR #325)

Fixes

  • Fix regression in 1b19d14 that caused DMARC record output to be None if a syntax error was found (Close #234)

5.13.2

11 Jan 01:45

Choose a tag to compare

  • Skip undecodable TXT records instead of raising exception during SPF lookup (PR #232 fixes issue #231)

5.13.1

29 Dec 17:39

Choose a tag to compare

  • Fix check_domains return type annotation (PR # 229 fixed issue #228)
  • Fix Dockerfile COPY destination path (PR #230 fixed issue #227)