checkdmarc

repository·main·Indexed 43 days ago

https://github.com/domainaware/checkdmarc

A comprehensive validation suite for email authentication DNS records, including SPF, DMARC, BIMI, MX, MTA-STS, and SMTP TLS. Available as a Python module, CLI, and web app, it provides bulk testing, DNS lookup counting, and VMC certificate verification for BIMI.

Tokens
25.1K
Snippets
67
Records
93
Agent score
55%

What's inside checkdmarc

  1. Overview of checkdmarc features

    main

    checkdmarc is a tool for validating SPF, DMARC, BIMI, MX, MTA-STS, and SMTP TLS records. It provides three interfaces: a Python API, a Command Line Interface (CLI), and a web application.

    Key capabilities include:

    • Bulk Testing: Test multiple domains simultaneously.
    • Output Formats: CLI supports JSON and CSV output.
    • SPF Validation: Validates records, counts DNS lookups (including void lookups), and tracks lookups per mechanism.
    • DMARC Validation: Parses records and warns about ineffective sp values or deprecated tags (pct/rf/ri) per RFC 9989. It also checks authorization for reporting email addresses.
    • BIMI Validation: Validates mark formats and certificates against Minimum Security Requirements.
    • MX & TLS: Validates MX preference and IP addresses. Supports optional STARTTLS and TLS testing via the --check-mx-tls flag, and uses DNSSEC/TLSA/DANE for certificate pinning.
    • Other Records: Supports MTA-STS, SMTP TLS reporting, SOA record parsing, and nameserver listing.
  2. Understand the role of VMC CA certificates in checkdmarc

    main

    The resources package in checkdmarc provides non-Python files necessary for verifying Verified Mark Certificates (VMCs). Specifically, the file VMACAs.pem aggregates multiple VMC Certificate Authority (CA) certificates to enable the verification of VMCs during DMARC checks.

    If you need to manually verify or update these certificates, checkdmarc relies on root certificates from the following providers:

    • DigiCert
    • GlobalSign
    • SSL.com

    For a list of recognized VMC issuers, refer to the BIMI Group VMC Issuers page.

  3. Configure Encrypted DNS (DoH and DoT)

    main

    You can specify different transport protocols for each entry in the --nameserver (or -n) list:

    • Plain DNS: Use an IP address (e.g., 1.1.1.1). Uses UDP/TCP port 53.
    • DNS over HTTPS (DoH): Use an https:// URL (e.g., https://cloudflare-dns.com/dns-query).
    • DNS over TLS (DoT): Use the tls:// prefix. The format is tls://ip[:port][#hostname]. The port defaults to 853. The #hostname is the SNI used for the TLS certificate identity. IPv6 addresses must be wrapped in brackets (e.g., tls://[2620:fe::fe]#dns.quad9.net).

    Example mixing protocols:

    checkdmarc -n https://cloudflare-dns.com/dns-query tls://9.9.9.9#dns.quad9.net example.com

    Proxy Configuration: If outbound DNS is blocked but an HTTP proxy is available, use DoH and set standard proxy environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY). checkdmarc will resolve the DoH server's hostname via the proxy.

    If the proxy inspects TLS, set SSL_CERT_FILE to your organization's CA bundle:

    export SSL_CERT_FILE=/etc/ssl/certs/corporate-ca.pem

    Important Constraints:

    • DoT connections are made directly to TCP port 853 and do not use a proxy. Use DoH if you are on a proxy-only network.
    • The --check-mx-tls option requires a direct connection to each MX host on port 25. Disable this if port 25 is blocked.
    checkdmarc -n https://cloudflare-dns.com/dns-query tls://9.9.9.9#dns.quad9.net example.com
  4. Best practice: Use multiple DNS resolvers for reliability

    main

    By default, checkdmarc uses your system's configured resolvers. For public-internet checks, it is highly recommended to pass a mix of public resolvers from different providers (e.g., Cloudflare, Google, Quad9). This provides cross-provider failover: if one provider is slow or incompatible with an authoritative server, the query falls through to the next provider within ~1 second.

    CLI Usage:

    checkdmarc -n 1.1.1.1 8.8.8.8 proton.me

    Python API Usage: Use the checkdmarc.RECOMMENDED_DNS_NAMESERVERS constant for the recommended pair.

    from checkdmarc import check_domains, RECOMMENDED_DNS_NAMES_SERVERS
    
    results = check_domains(
        ["proton.me"],
        nameservers=RECOMMENDED_DNS_NAMESERVERS,
    )

    Note on Failures: A nameserver that fails (timeout or transport error) is moved behind other configured nameservers for 60 seconds. This cooldown period can be adjusted using the DNS_NAMESERVER_FAILURE_COOLDOWN_SECONDS environment variable.

    from checkdmarc import check_domains, RECOMMENDED_DNS_NAMESERVERS
    
    results = check_domains(
        ["proton.me"],
        nameservers=RECOMMENDED_DNS_NAMESERVERS,
    )
  5. Install checkdmarc

    main

    To install or upgrade to the latest stable release of checkdmarc on macOS or Linux, use pip3.

    Prerequisites:

    • Python 3.10 or later.
    • On Debian or Ubuntu systems, ensure python3-pip is installed via sudo apt-get install python3-pip.

    Windows Note: On Windows, use pip instead of pip3.

    pip3 install -U checkdmarc
  6. Use checkdmarc via Docker

    main

    You can run checkdmarc using Docker by building the image locally and then running it against a target domain.

    To build the image:

    docker build . -t checkdmarc

    To run a check against a domain (e.g., google.nl):

    docker run --rm checkdmarc google.nl
    docker build . -t checkdmarc
    docker run --rm checkdmarc google.nl
  7. Understand DMARC tag definitions and values

    main

    The checkdmarc library provides a comprehensive map of DMARC tags and their valid values. This is useful for understanding the expected structure of a record.

    Core Tags:

    • v: Version (Required). Must be DMARC1 and must be the first tag.
    • p: Requested Mail Receiver Policy. Values: none, quarantine, reject.
    • sp: Subdomain Policy. Values: none, quarantine, reject.
    • np: Non-existent Subdomain Policy. Values: none, quarantine, reject.
    • adkim: DKIM Alignment Mode. Values: r (relaxed, default), s (strict).
    • aspf: SPF Alignment Mode. Values: r (relaxed, default), s (strict).
    • fo: Failure Reporting Options. Values: 0, 1, d, s.
    • t: DMARC Policy Test Mode. Values: n (default), y.
    • psd: PSD Flag. Values: y, n, u (default).
    • rua: Aggregate Feedback Addresses. A list of URIs.
    • ruf: Forensic Feedback Addresses. A list of URIs.
  8. Use custom caches for DNSSEC operations

    main

    All primary DNSSEC functions (check_dnssec, get_dnskey, get_tlsa_records) accept an optional cache argument of type ExpiringDict.

    Providing a custom cache allows you to isolate cache state between different parts of your application or prevent global state pollution. If no cache is provided, the functions use internal module-level caches (DNSSEC_CACHE, DNSKEY_CACHE, or TLSA_CACHE).

    from expiringdict import ExpiringDict
    from checkdmarc.dnssec import check_dnssec
    
    # Create a custom cache for your application session
    my_cache = ExpiringDict(max_len=100, max_age_seconds=3600)
    
    # Pass it to the function
    result = check_dnssec("example.com", cache=my_cache)
  9. Handle the `redirect` modifier in SPF records

    main

    The redirect modifier directs the SPF evaluation to a different domain.

    • Constraint: If an all mechanism is present anywhere in the record, the redirect modifier MUST be ignored (RFC 7208 § 6.1).
    • Error Condition: If multiple redirect modifiers appear in the same record, it is a permanent error (SPFSyntaxError).
    • Loop Detection: If the redirect target leads back to a domain already in the recursion stack, an SPFRedirectLoop is raised.
  10. Understand the DomainCheckResult structure

    main

    A DomainCheckResult is a dictionary (specifically a TypedDict) containing the validation results for a single domain.

    Fields:

    • domain (str): The domain name.
    • base_domain (str): The base domain.
    • dnssec (bool): True if the zone's DNSSEC is valid/signed; False otherwise.
    • soa (SOARecordResults): Start of Authority record information.
    • ns (NameserverResult): Nameserver information and warnings.
    • mx (MXResults): Mail exchanger records and STARTTLS test results.
    • spf (SPFRecordResults): SPF record validation results.
    • dmarc (DMARCResults | DMARCErrorResults): DMARC record validation results.
    • smtp_tls_reporting (SMTPTLSReportingResult): SMTP TLS reporting configuration.
    • mta_sts (MTASTSCheckResult): MTA-STS policy validation results.
    • bimi (BIMICheckResult, optional): BIMI record validation results (present if bimi_selector was provided).
  11. Configure cache settings via environment variables

    main

    Starting in version 5.11.0, you can control cache behavior using environment variables. By default, all caches have a maximum length of 200000 and a maximum age of 1800 seconds.

    To apply settings globally to all caches, use CACHE_MAX_LEN and CACHE_MAX_AGE_SECONDS. To target specific cache types, use the prefixed versions listed below.

    # Example: Set global cache limits
    export CACHE_MAX_LEN=50000
    export CACHE_MAX_AGE_SECONDS=3600
    
    # Example: Set specific DNS cache limits
    export DNS_CACHE_MAX_LEN=10000
    export DNS_CACHE_MAX_AGE_SECONDS=600