API

checkdmarc

Validates and parses email-related DNS records

class checkdmarc.DomainCheckResult[source]

Result of checking a single domain

checkdmarc.check_domains(domains: list[str], *, parked: bool = False, approved_nameservers: Sequence[str | Nameserver] | None = None, approved_mx_hostnames: list[str] | None = None, check_mx_tls: bool = False, skip_tls: bool | None = None, bimi_selector: str = 'default', include_tag_descriptions: bool = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0, wait: float = 0.0) DomainCheckResult | list[DomainCheckResult][source]

Check the given domains for email security records (SPF, DMARC, MX/STARTTLS, DNSSEC, SOA, NS, MTA-STS, SMTP TLS Reporting, and BIMI), parse them, and return the results

Parameters:
  • domains (list) – A list of domains to check

  • parked (bool) – Indicates that the domains are parked

  • approved_nameservers (list) – A list of approved nameserver substrings

  • approved_mx_hostnames (list) – A list of approved MX hostname substrings

  • check_mx_tls (bool) – Test each MX host for STARTTLS and TLS support (off by default)

  • skip_tls (bool) – Deprecated, no effect — TLS testing is opt-in via check_mx_tls

  • bimi_selector (str) – The BIMI selector to test

  • include_tag_descriptions (bool) – Include descriptions of tags and/or tag values in the results

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

  • wait (float) – number of seconds to wait between processing domains

Returns:

A single DomainCheckResult (when one domain is provided) or a list of DomainCheckResult (when multiple domains are provided).

Each DomainCheckResult contains:

  • domain - The domain name

  • base_domain - The base domain

  • dnssec - True when the domain’s zone has a DS record at its parent and the zone’s DNSKEY and record signatures verify against it; False for unsigned or broken zones (bool — see checkdmarc.dnssec.check_dnssec() for the trust assumptions)

  • soa - Start of Authority record information

  • ns - Nameserver information and warnings

  • mx - Mail exchanger records and STARTTLS test results

  • spf - SPF record validation results

  • dmarc - DMARC record validation results

  • smtp_tls_reporting - SMTP TLS reporting configuration

  • mta_sts - MTA-STS policy validation results

  • bimi - BIMI record validation results (optional, only if bimi_selector is not None)

checkdmarc.check_ns(domain: str, *, approved_nameservers: Sequence[str | Nameserver] | None = None, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) NameserverResultOk | NameserverResultError[source]

Returns a dictionary of nameservers and warnings or a dictionary with an empty list and an error.

Parameters:
  • domain (str) – A domain name

  • approved_nameservers (list) – A list of approved nameserver substrings

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A dictionary with the following keys:

  • hostnames - A list of nameserver hostnames

  • warnings - A list of warnings

If a DNS error occurs, the dictionary will have the following keys:

  • hostnames - An empty list

  • error - An error message

Return type:

dict

checkdmarc.output_to_file(path: str, content: str)[source]

Write given content to the given path

Parameters:
  • path (str) – A file path

  • content (str) – JSON or CSV text

checkdmarc.results_to_csv(results: DomainCheckResult | list[DomainCheckResult]) str[source]

Converts a dictionary of results to CSV

Parameters:

results (dict or list) – A dictionary of results, or a list of them

Returns:

A CSV of results

Return type:

str

checkdmarc.results_to_csv_rows(results: DomainCheckResult | list[DomainCheckResult]) list[dict][source]

Converts a results dictionary or list of dictionaries to a list of CSV row dictionaries

Parameters:

results (dict or list) – A dictionary of results, or a list of them

Returns:

A list of CSV row dictionaries

Return type:

list

checkdmarc.results_to_json(results: DomainCheckResult | list[DomainCheckResult]) str[source]

Converts a dictionary of results or list of results to a JSON string

Parameters:

results (dict or list) – A dictionary of results, or a list of them

Returns:

Results in JSON format

Return type:

str

checkdmarc.bimi

Brand Indicators for Message Identification (BIMI) record validation

class checkdmarc.bimi.BIMICheckResult[source]

Result from checking BIMI for a domain

exception checkdmarc.bimi.BIMIError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.bimi.BIMIParseResult[source]

Result from parsing a BIMI record

class checkdmarc.bimi.BIMIQueryResult[source]

Result from querying a BIMI record

exception checkdmarc.bimi.BIMIRecordInWrongLocation(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.bimi.BIMIRecordNotFound(error)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.bimi.BIMISyntaxError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.bimi.BIMITagValue[source]

BIMI tag value structure

value is a list only for the lps tag, whose value is a comma-separated list of local-part prefixes.

class checkdmarc.bimi.CertificateMetadata[source]

Metadata about a Verified Mark Certificate (VMC)

exception checkdmarc.bimi.InvalidBIMIIndicatorURI(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.bimi.InvalidBIMITag(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.bimi.InvalidBIMITagValue(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.bimi.MultipleBIMIRecords(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.bimi.SPFRecordFoundWhereBIMIRecordShouldBe(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.bimi.SVGMetadata[source]

Metadata extracted from SVG image

exception checkdmarc.bimi.UnrelatedTXTRecordFoundAtBIMI(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

checkdmarc.bimi.check_bimi(domain: str, *, selector: str = 'default', parsed_dmarc_record: DMARCResults | DMARCErrorResults | None = None, include_tag_descriptions: bool = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) BIMICheckResult[source]

Returns a dictionary with a parsed BIMI record or an error.

Note

This will attempt to download and validate the SVG image and mark certificate at the URLs provided in the BIMI record; a download or processing failure is reported as an error entry under image or certificate.

Parameters:
  • domain (str) – A domain name

  • selector (str) – The BIMI selector

  • parsed_dmarc_record (dict) – A parsed DMARC record

  • include_tag_descriptions (bool) – Include descriptions in parsed results

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:

  • record - The BIMI record string

  • valid - True

  • selector - The BIMI selector

  • location - The domain where the record was found

  • tags - The parsed BIMI record tags

  • image - SVG image metadata, if any

  • certificate - Mark certificate metadata, if any

  • warnings - A list of warnings

If a DNS error occurs, the dictionary will have the following keys:

  • error - The error message

  • valid - False

Return type:

dict

checkdmarc.bimi.get_certificate_metadata(pem_crt: bytes, *, domain=None) dict[str, Any][source]

Get metadata about a Verified Mark Certificate (VMC)

checkdmarc.bimi.parse_bimi_record(record: str, *, domain: str | None = None, parsed_dmarc_record: DMARCResults | DMARCErrorResults | None = None, include_tag_descriptions: bool = False, syntax_error_marker: str = '➞', http_timeout: float = 2.0) dict[str, Any][source]

Parses a BIMI record

Parameters:
  • record (str) – A BIMI record

  • domain (str) – The domain where the BIMI record was located

  • parsed_dmarc_record (dict) – A parsed DMARC record

  • include_tag_descriptions (bool) – Include descriptions in parsed results

  • syntax_error_marker (str) – The marker for pointing out syntax errors

  • http_timeout (float) – HTTP timeout in seconds

Returns:

a dict with the following keys:
  • tags - a dict of BIMI tags

    • value - The BIMI tag value

    • description - A description of the tag/value

  • image - SVG image metadata, if any

  • certificate - Verified Mark Certificate (VMC) metadata, if any

  • warnings - A list of warnings

Note

This will attempt to download and validate the SVG image and mark certificate at the URLs provided in the BIMI record; a download or processing failure is reported as an error entry under image or certificate.

Note

description is only included if include_tag_descriptions is set to True

Return type:

dict

Raises:
checkdmarc.bimi.query_bimi_record(domain: str, *, selector: str | None = 'default', nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) BIMIQueryResult[source]

Queries DNS for a BIMI record

Parameters:
  • domain (str) – A domain name

  • selector (str) – The BIMI selector

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:
  • record - the unparsed BIMI record string

  • location - the domain where the record was found

  • warnings - warning conditions found

Return type:

dict

Raises:

checkdmarc.dmarc

DMARC record validation

exception checkdmarc.dmarc.DMARCError(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

class checkdmarc.dmarc.DMARCErrorData[source]

Optional data structure for DMARCError

class checkdmarc.dmarc.DMARCErrorResults[source]

Error return type for check_dmarc

class checkdmarc.dmarc.DMARCRecord[source]

Return type for get_dmarc_record without descriptions

exception checkdmarc.dmarc.DMARCRecordInWrongLocation(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

exception checkdmarc.dmarc.DMARCRecordNotFound(error)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

class checkdmarc.dmarc.DMARCRecordQueryResults[source]
exception checkdmarc.dmarc.DMARCRecordStartsWithWhitespace(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

class checkdmarc.dmarc.DMARCRecordWithDescriptions[source]

Return type for get_dmarc_record with descriptions

exception checkdmarc.dmarc.DMARCReportEmailAddressMissingMXRecords[source]

Raised when an email address in a DMARC report URI is missing MX records

class checkdmarc.dmarc.DMARCResults[source]

Success return type for check_dmarc

exception checkdmarc.dmarc.DMARCSyntaxError(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

class checkdmarc.dmarc.DMARCTagDetails[source]
class checkdmarc.dmarc.DMARCTagMap[source]
class checkdmarc.dmarc.DMARCTagMapItem[source]
class checkdmarc.dmarc.DMARCTagMapItemWithDefault[source]
class checkdmarc.dmarc.DMARCTagMapItemWithDefaultAndValues[source]
class checkdmarc.dmarc.DMARCTagMapItemWithValues[source]
class checkdmarc.dmarc.DMARCTagValue[source]

Base structure for a DMARC tag value without descriptions

class checkdmarc.dmarc.DMARCTagValueWithDescription[source]

Structure for a DMARC tag value with descriptions

exception checkdmarc.dmarc.InvalidDMARCReportURI(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

exception checkdmarc.dmarc.InvalidDMARCTag(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

exception checkdmarc.dmarc.InvalidDMARCTagValue(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

exception checkdmarc.dmarc.MultipleDMARCRecords(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

class checkdmarc.dmarc.ParsedDMARCRecord[source]

Return type for parse_dmarc_record without descriptions

class checkdmarc.dmarc.ParsedDMARCRecordWithDescriptions[source]

Return type for parse_dmarc_record with descriptions

class checkdmarc.dmarc.ParsedDMARCReportURI[source]

Structure for a parsed DMARC report URI

exception checkdmarc.dmarc.SPFRecordFoundWhereDMARCRecordShouldBe(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

exception checkdmarc.dmarc.UnrelatedTXTRecordFoundAtDMARC(msg: str, data: DMARCErrorData | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (DMARCErrorData) – A dictionary of data to include in the results

exception checkdmarc.dmarc.UnverifiedDMARCURIDestination[source]

Raised when the destination of a DMARC report URI does not indicate that it accepts reports for the domain

checkdmarc.dmarc.check_dmarc(domain: str, *, parked: bool = False, include_dmarc_tag_descriptions: bool = False, ignore_unrelated_records: bool = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) DMARCResults | DMARCErrorResults[source]

Returns a dictionary with a parsed DMARC record or an error

Parameters:
  • domain (str) – A domain name

  • parked (bool) – The domain is parked

  • include_dmarc_tag_descriptions (bool) – Include tag descriptions

  • ignore_unrelated_records (bool) – Ignore unrelated TXT records

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:

  • record - the unparsed DMARC record string

  • location - the domain where the record was found

  • valid - True

  • tags - a dict of parsed DMARC tags

  • warnings - warning conditions found

If a DNS error occurs, the dictionary will have the following keys:

  • error - An error message

  • valid - False

Return type:

dict

checkdmarc.dmarc.check_wildcard_dmarc_report_authorization(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, ignore_unrelated_records: bool = False, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) bool[source]

Checks for a wildcard DMARC report authorization record, e.g.:

*._report.example.com IN TXT "v=DMARC1"
Parameters:
  • domain (str) – The domain to check

  • nameservers (list) – A list of nameservers to query

  • ignore_unrelated_records (bool) – Ignore unrelated TXT records

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

An indicator of the existence of a valid wildcard DMARC report authorization record

Return type:

bool

checkdmarc.dmarc.get_dmarc_record(domain: str, *, include_tag_descriptions: Literal[False] = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = DEFAULT_DNS_TIMEOUT, retries: int = DEFAULT_DNS_MAX_RETRIES) DMARCRecord[source]
checkdmarc.dmarc.get_dmarc_record(domain: str, *, include_tag_descriptions: Literal[True], nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = DEFAULT_DNS_TIMEOUT, retries: int = DEFAULT_DNS_MAX_RETRIES) DMARCRecordWithDescriptions

Retrieves a DMARC record for a domain and parses it

Parameters:
  • domain (str) – A domain name

  • include_tag_descriptions (bool) – Include descriptions in parsed results

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:

Return type:

dict

Raises:
checkdmarc.dmarc.get_dmarc_tag_description(tag: str, value: str | list[str] | None = None) DMARCTagDetails[source]

Get the name, default value, and description for a DMARC tag, and/or a description for a tag value

Parameters:
  • tag (str) – A DMARC tag

  • value – An optional value

Returns:

a dict with the following keys:
  • name - the tag name

  • default- the tag’s default value

  • description - A description of the tag or value

Return type:

dict

checkdmarc.dmarc.parse_dmarc_record(record: str, domain: str, *, parked: bool = False, include_tag_descriptions: Literal[False] = False, nameservers: Sequence[str | Nameserver] | None = None, ignore_unrelated_records: bool = False, resolver: Resolver | None = None, timeout: float = DEFAULT_DNS_TIMEOUT, retries: int = DEFAULT_DNS_MAX_RETRIES, syntax_error_marker: str = SYNTAX_ERROR_MARKER) ParsedDMARCRecord[source]
checkdmarc.dmarc.parse_dmarc_record(record: str, domain: str, *, parked: bool = False, include_tag_descriptions: Literal[True], nameservers: Sequence[str | Nameserver] | None = None, ignore_unrelated_records: bool = False, resolver: Resolver | None = None, timeout: float = DEFAULT_DNS_TIMEOUT, retries: int = DEFAULT_DNS_MAX_RETRIES, syntax_error_marker: str = SYNTAX_ERROR_MARKER) ParsedDMARCRecordWithDescriptions

Parses a DMARC record

Parameters:
  • record (str) – A DMARC record

  • domain (str) – The domain where the record is found

  • parked (bool) – Indicates if a domain is parked

  • include_tag_descriptions (bool) – Include descriptions in parsed results

  • nameservers (list) – A list of nameservers to query

  • ignore_unrelated_records (bool) – Ignore unrelated TXT records

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

  • syntax_error_marker (str) – The marker for pointing out syntax errors

Returns:

a dict with the following keys:
  • tags - a dict of DMARC tags

    • value - The DMARC tag value

    • explicit - bool: A value is explicitly set

    • default - The tag’s default value

    • description - A description of the tag/value

  • warnings - A list of warnings

Note

default and description are only included if include_tag_descriptions is set to True

Return type:

dict

Raises:
checkdmarc.dmarc.parse_dmarc_report_uri(uri: str) ParsedDMARCReportURI[source]

Parses a DMARC Reporting (i.e. rua/ruf) URI

Note

RFC 9989 § 4.7 allows any valid URI, but mailto is the only scheme mail receivers are required to support. For a non-mailto URI, address contains the full URI and size_limit is None.

Parameters:

uri – A DMARC URI

Returns:

a dict of the URI’s components:
  • scheme

  • address

  • size_limit

Return type:

dict

Raises:

checkdmarc.dmarc.InvalidDMARCReportURI

checkdmarc.dmarc.query_dmarc_record(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0, ignore_unrelated_records: bool = False) DMARCRecordQueryResults[source]

Queries DNS for a DMARC record

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

  • ignore_unrelated_records (bool) – Ignore unrelated TXT records

Returns:

a dict with the following keys:
  • record - the unparsed DMARC record string

  • location - the domain where the record was found

  • warnings - warning conditions found

Return type:

dict

Raises:

checkdmarc.dmarc.DMARCRecordNotFound checkdmarc.dmarc.DMARCRecordInWrongLocation checkdmarc.dmarc.MultipleDMARCRecords checkdmarc.dmarc.SPFRecordFoundWhereDMARCRecordShouldBe

checkdmarc.dmarc.verify_dmarc_report_destination(source_domain: str, destination_domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, ignore_unrelated_records: bool = False, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) None[source]

Checks if the report destination accepts reports for the source domain per RFC 9990, § 4 (the authorization-record check, previously in RFC 7489 § 7.1). Raises checkdmarc.dmarc.UnverifiedDMARCURIDestination if it doesn’t accept.

Parameters:
  • source_domain (str) – The source domain

  • destination_domain (str) – The destination domain

  • nameservers (list) – A list of nameservers to query

  • ignore_unrelated_records (bool) – Ignore unrelated TXT records

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Raises:

checkdmarc.dnssec

DNSSEC tests

checkdmarc.dnssec.check_dnssec(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, timeout: float = 2.0, cache: ExpiringDict | None = None) bool[source]

Check that DNSSEC protects the given domain’s records

True means the chain from the parent zone held together when this function checked it directly:

  • The parent zone publishes a DS record for the domain’s zone (the domain itself, or its base domain when the domain is not a zone apex)

  • The zone’s DNSKEY record set contains a key whose digest matches that DS record (RFC 4034 section 5)

  • The signature over the DNSKEY record set verifies against a DS-matched key (RFC 4035 section 5)

  • For a domain below the zone apex, a record set at the domain itself (MX, A, AAAA, NS, TXT, or CNAME) carries a signature that verifies against those keys

False covers every other outcome, and the log tells them apart: an unsigned zone (no DS record at the parent — including a zone that publishes a DNSKEY anyway, which validating resolvers treat as unsigned per RFC 4033 section 4.3), a broken zone whose parent publishes a DS record that its keys or signatures do not live up to (logged as a warning, because mail from such a domain is rejected by receivers that validate), and a lookup that could not complete (not cached).

Trust assumptions: the DS record itself arrives over an unauthenticated channel unless the configured resolver validates (the AD flag on its answers, logged at debug level, says whether it claims to). This is a one-level chain check anchored at the DS record the resolver reports, not a full validator walking signatures down from the root, so a resolver — or an attacker able to spoof its answers — that forges the DS record along with everything below it would not be caught.

Parameters:
  • domain (str) – The domain to check

  • nameservers (list) – A list of nameservers to query

  • timeout (float) – Timeout in seconds

  • cache (ExpiringDict) – Cache

Returns:

DNSSEC status

Return type:

bool

checkdmarc.dnssec.get_dnskey(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, timeout: float = 2.0, cache: ExpiringDict | None = None) dict | None[source]

Get a DNSKEY RRSet on the given domain

Parameters:
  • domain (str) – The domain to check

  • nameservers (list) – A list of nameservers to query

  • timeout (float) – Timeout in seconds

  • cache (ExpiringDict) – A cache

Returns:

A DNSKEY dictionary if a DNSKEY is found

checkdmarc.dnssec.get_tlsa_records(hostname: str, *, nameservers: Sequence[str | Nameserver] | None = None, timeout: float = 2.0, port: int = 25, protocol: str = 'tcp', cache: ExpiringDict | None = None) list[str][source]

Checks for TLSA records on the given hostname

Parameters:
  • hostname (str) – The hostname to check

  • nameservers (list) – A list of nameservers to query

  • timeout (float) – Timeout in seconds

  • port (int) – The port

  • protocol (str) – The protocol

  • cache (ExpiringDict) – A cache

Returns:

A list of TLSA records

Return type:

list

checkdmarc.dnssec.test_dnssec(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, timeout: float = 2.0, cache: ExpiringDict | None = None) bool[source]

Deprecated alias for check_dnssec()

checkdmarc.mta_sts

SMTP MTA Strict Transport Security (MTA-STS) validation

class checkdmarc.mta_sts.DownloadedMTASTSPolicy[source]
exception checkdmarc.mta_sts.InvalidMTASTSTag(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.mta_sts.InvalidSTSTagValue(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.mta_sts.MTASTSCheckFailure[source]
class checkdmarc.mta_sts.MTASTSCheckSuccess[source]
exception checkdmarc.mta_sts.MTASTSError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.mta_sts.MTASTSFailure[source]
exception checkdmarc.mta_sts.MTASTSPolicyDownloadError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.mta_sts.MTASTSPolicyError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.mta_sts.MTASTSPolicyParsingResults[source]
exception checkdmarc.mta_sts.MTASTSPolicySyntaxError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.mta_sts.MTASTSQueryResult[source]
checkdmarc.mta_sts.MTASTSQueryResults

alias of MTASTSQueryResult

exception checkdmarc.mta_sts.MTASTSRecordInWrongLocation(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.mta_sts.MTASTSRecordNotFound(error)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.mta_sts.MTASTSRecordSyntaxError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.mta_sts.MTASTSSuccess[source]
exception checkdmarc.mta_sts.MultipleMTASTSRecords(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.mta_sts.ParsedMTASTSPolicy[source]
class checkdmarc.mta_sts.ParsedMTASTSRecord[source]
exception checkdmarc.mta_sts.SPFRecordFoundWhereMTASTSRecordShouldBe(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.mta_sts.UnrelatedTXTRecordFoundAtMTASTS(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

checkdmarc.mta_sts.check_mta_sts(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) MTASTSCheckSuccess | MTASTSCheckFailure[source]

Returns a dictionary with a parsed MTA-STS policy or an error.

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:

  • id - The MTA-STS DNS record ID

  • policy - The parsed MTA-STS policy

  • valid - True

  • warnings - A list of warnings

If an error occurs, the dictionary will have the following keys:

  • error - The error message

  • valid - False

Return type:

dict

checkdmarc.mta_sts.download_mta_sts_policy(domain: str, *, http_timeout: float = 2.0) DownloadedMTASTSPolicy[source]

Downloads a domain’s MTA-STS policy

Parameters:
  • domain (str) – A domain name

  • http_timeout (float) – HTTP timeout in seconds

Returns:

a dict with the following keys:
  • policy - The unparsed policy string

  • warnings - A list of any warning conditions found

Return type:

dict

Raises:

checkdmarc.mta_sts.MTASTSPolicyDownloadError

checkdmarc.mta_sts.mx_in_mta_sts_patterns(mx_hostname: str, mta_sts_mx_patterns: list[str]) bool[source]

Tests whether a given MX hostname is covered by a given list of MX patterns from an MTA-STS policy.

Parameters:
  • mx_hostname (str) – The MX hostname to test

  • mta_sts_mx_patterns (list) – The list of MTA-STS MX patterns

Returns: True if the MX hostname is included, False if not

checkdmarc.mta_sts.parse_mta_sts_policy(policy: str) MTASTSPolicyParsingResults[source]

Parses an MTA-STS policy

Parameters:

policy – The policy

Raises:

checkdmarc.mta_sts.MTASTSPolicySyntaxError

checkdmarc.mta_sts.parse_mta_sts_record(record: str, *, include_tag_descriptions: bool = False, syntax_error_marker: str = '➞') ParsedMTASTSRecord[source]

Parses an MTA-STS record

Parameters:
  • record (str) – An MTA-STS record

  • include_tag_descriptions (bool) – Include descriptions in parsed results

  • syntax_error_marker (str) – The marker for pointing out syntax errors

Returns:

a dict with the following keys:
  • tags - a dict mapping each MTA-STS tag to its string value

  • warnings - A list of warnings

Note

include_tag_descriptions is accepted for API consistency with the other record parsers, but MTA-STS tag values are plain strings and no descriptions are currently added

Return type:

dict

Raises:
checkdmarc.mta_sts.query_mta_sts_record(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) MTASTSQueryResult[source]

Queries DNS for an MTA-STS record

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:
  • record - the unparsed MTA-STS record string

  • warnings - warning conditions found

Return type:

dict

Raises:

checkdmarc.smtp_tls_reporting

SMTP TLS Reporting

exception checkdmarc.smtp_tls_reporting.InvalidSMTPTLSReportingTag(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.smtp_tls_reporting.InvalidSMTPTLSReportingTagValue(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.smtp_tls_reporting.MultipleSMTPTLSReportingRecords(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.smtp_tls_reporting.ParsedSMTPTLSReportingRecord[source]
exception checkdmarc.smtp_tls_reporting.SMTPTLSReportingError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.smtp_tls_reporting.SMTPTLSReportingFailure[source]
class checkdmarc.smtp_tls_reporting.SMTPTLSReportingQueryResult[source]
checkdmarc.smtp_tls_reporting.SMTPTLSReportingQueryResults

alias of SMTPTLSReportingQueryResult

exception checkdmarc.smtp_tls_reporting.SMTPTLSReportingRecordInWrongLocation(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.smtp_tls_reporting.SMTPTLSReportingRecordNotFound(error)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.smtp_tls_reporting.SMTPTLSReportingSuccess[source]
exception checkdmarc.smtp_tls_reporting.SMTPTLSReportingSyntaxError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

class checkdmarc.smtp_tls_reporting.SMTPTLSReportingTagValue[source]
class checkdmarc.smtp_tls_reporting.SMTPTLSReportingTagValueWithDescription[source]
exception checkdmarc.smtp_tls_reporting.SPFRecordFoundWhereTLSRPTShouldBe(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

exception checkdmarc.smtp_tls_reporting.UnrelatedTXTRecordFoundAtTLSRPT(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the results

checkdmarc.smtp_tls_reporting.check_smtp_tls_reporting(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) SMTPTLSReportingSuccess | SMTPTLSReportingFailure[source]

Returns a dictionary with a parsed SMTP TLS Reporting record or an error.

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:

  • valid - True

  • tags - A dictionary of tags and values

  • warnings - A list of warnings

If an error occurs, the dictionary will have the following keys:

  • error - The error message

  • valid - False

Return type:

dict

checkdmarc.smtp_tls_reporting.parse_smtp_tls_reporting_record(record: str, *, include_tag_descriptions: bool = False, syntax_error_marker: str = '➞') ParsedSMTPTLSReportingRecord[source]

Parses an SMTP TLS Reporting record

Parameters:
  • record (str) – An SMTP TLS Reporting record

  • include_tag_descriptions (bool) – Include descriptions in parsed results

  • syntax_error_marker (str) – The marker for pointing out syntax errors

Returns:

a dict with the following keys:
  • tags - a dict of SMTP TLS Reporting tags

    • value - The SMTP TLS Reporting tag value

    • description - A description of the tag/value

  • warnings - A list of warnings

Note

description is only included if include_tag_descriptions is set to True

Return type:

dict

Raises:
checkdmarc.smtp_tls_reporting.query_smtp_tls_reporting_record(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) SMTPTLSReportingQueryResult[source]

Queries DNS for an SMTP TLS Reporting record

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:
  • record - the unparsed SMTP TLS Reporting record

  • warnings - warning conditions found

Return type:

dict

Raises:

checkdmarc.smtp

SMTP tests

class checkdmarc.smtp.MXResultsFailure[source]
class checkdmarc.smtp.MXResultsSuccess[source]
exception checkdmarc.smtp.SMTPError[source]

Raised when an SMTP error occurs

checkdmarc.smtp.check_mx(domain: str, *, approved_mx_hostnames: list[str] | None = None, mta_sts_mx_patterns: list[str] | None = None, check_mx_tls: bool = False, skip_tls: bool | None = None, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) MXResultsSuccess | MXResultsFailure[source]

Gets MX hostnames and their addresses, or an empty list of hosts and an error if a DNS error occurs

Parameters:
  • domain (str) – A domain name

  • check_mx_tls (bool) – Test each MX host for STARTTLS and TLS support (off by default)

  • skip_tls (bool) – Deprecated, no effect — TLS testing is opt-in via check_mx_tls

  • approved_mx_hostnames (list) – A list of approved MX hostname substrings

  • mta_sts_mx_patterns (list) – A list of MX patterns from MTA-STS

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:

  • hosts - A list of dict with keys of

    • preference - The MX preference integer

    • hostname - A hostname

    • dnssec - DNSSEC status

    • addresses - A list of IP addresses

    • tlsa - A list of TLSA records, if they exist

    • tls - TLS support status (absent if TLS testing is skipped)

    • starttls - STARTTLS support status (absent if TLS testing is skipped)

  • warnings - A list of MX resolution warnings

If a DNS error occurs, the dictionary will have the following keys:

  • hosts - An empty list

  • error - An error message

Return type:

dict

checkdmarc.smtp.get_mx_hosts(domain: str, *, check_mx_tls: bool = False, skip_tls: bool | None = None, approved_mx_hostnames: list[str] | None = None, approved_hostnames: list[str] | None = None, mta_sts_mx_patterns: list[str] | None = None, parked: bool = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) MXResultsSuccess[source]

Gets MX hostnames and their addresses

Parameters:
  • domain (str) – A domain name

  • check_mx_tls (bool) – Test each MX host for STARTTLS and TLS support (off by default)

  • skip_tls (bool) – Deprecated, no effect — TLS testing is opt-in via check_mx_tls

  • approved_mx_hostnames (list) – A list of approved MX hostname substrings

  • approved_hostnames (list) – Deprecated alias for approved_mx_hostnames

  • mta_sts_mx_patterns (list) – A list of MX patterns from MTA-STS

  • parked (bool) – Indicates that the domain is parked

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

a dict with the following keys:
  • hosts - A list of dict with keys of

    • preference - The MX preference integer

    • hostname - A hostname

    • dnssec - DNSSEC status

    • addresses - A list of IP addresses

    • tlsa - A list of TLSA records, if they exist

    • tls - TLS support status (absent if TLS testing is skipped)

    • starttls - STARTTLS support status (absent if TLS testing is skipped)

  • warnings - A list of MX resolution warnings

Return type:

dict

checkdmarc.smtp.test_starttls(hostname: str, *, ssl_context: SSLContext | None = None, cache: ExpiringDict | None = None, timeout: float = 5.0) bool[source]

Attempt to connect to an SMTP server and validate STARTTLS support

Parameters:
  • hostname (str) – The hostname

  • cache (ExpiringDict) – Cache storage

  • ssl_context (SSLContext) – An SSL context

  • timeout (float) – Number of seconds to wait for the SMTP server (default 5.0)

Returns:

True if STARTTLS supported

Return type:

bool

Raises:

checkdmarc.smtp.SMTPError – SMTP connection failed

checkdmarc.smtp.test_tls(hostname: str, *, ssl_context: SSLContext | None = None, cache: ExpiringDict | None = None, timeout: float = 5.0) bool[source]

Attempt to connect to an SMTP server on port 465 and validate TLS/SSL support

Parameters:
  • hostname (str) – The hostname

  • cache (ExpiringDict) – Cache storage

  • ssl_context (SSLContext) – An SSL context

  • timeout (float) – Number of seconds to wait for the SMTP server (default 5.0)

Returns:

True if TLS supported

Return type:

bool

Raises:

checkdmarc.smtp.SMTPError – SMTP connection failed

checkdmarc.soa

class checkdmarc.soa.ParsedSOARecord[source]
class checkdmarc.soa.SOARecordError[source]
class checkdmarc.soa.SOARecordSuccessful[source]
checkdmarc.soa.check_soa(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) SOARecordSuccessful | SOARecordError[source]

Returns a dictionary with a domain’s SOA record and its parsed values, or a dictionary with the record (None on a DNS error) and an error.

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A dictionary with the following keys:

  • record - The SOA record as a string

  • values - A parsed version of the SOA record

If a parsing error occurs, the dictionary will have the following keys:

  • record - the SOA record

  • error - An error message

Return type:

dict

checkdmarc.soa.parse_soa_string(rr: str) ParsedSOARecord[source]

Parses a raw SOA record string and returns a dict with validated fields.

checkdmarc.soa.soa_rname_to_email(rname: str) str[source]

Converts a SOA RNAME domain-style name into an RFC 822 email address.

The first label of the RNAME is the local part of the address and the rest is the domain. The label boundary is the first unescaped dot, found by walking the string and consuming RFC 1035 section 5.1 escapes as we go: \X stands for the literal character X (so \. is a dot inside the local part and \\ is a literal backslash), and \DDD (exactly three decimal digits) stands for the byte with that value. A simple regex lookbehind gets a\\.b.example.com. wrong: the dot there follows an escaped backslash, so it is a real label boundary (local part a\, domain b.example.com).

A decoded local part that is not a plain dot-atom (for example one holding a space or @) is returned as an RFC 5322 quoted-string, so the result is always a syntactically valid address; a local part holding a character no valid address can carry (a control character or a byte outside ASCII) raises ValueError. Escapes in the domain labels are decoded the same way, and each label is validated on its own before the labels are joined with dots: a domain has no quoted form to fall back to, so a label that decodes to something an email domain label cannot carry — including a literal dot, which would silently move the label boundary — raises ValueError.

checkdmarc.spf

Sender Policy Framework (SPF) record validation

exception checkdmarc.spf.MultipleSPFRTXTRecords(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

class checkdmarc.spf.ParsedSPFMXMechanism[source]
class checkdmarc.spf.ParsedSPFRecord[source]
class checkdmarc.spf.ParsedSPFRecordError[source]
class checkdmarc.spf.ParsedSPFRecordSuccess[source]
class checkdmarc.spf.SPFAMechanism[source]
class checkdmarc.spf.SPFDNSLookupMechanism[source]
exception checkdmarc.spf.SPFError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

exception checkdmarc.spf.SPFIncludeLoop(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

class checkdmarc.spf.SPFIncludeMechanism[source]
class checkdmarc.spf.SPFMechanism[source]
class checkdmarc.spf.SPFQueryResults[source]
exception checkdmarc.spf.SPFRecordNotFound(error: Exception | str, domain: str)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

class checkdmarc.spf.SPFRedirect[source]
exception checkdmarc.spf.SPFRedirectLoop(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

exception checkdmarc.spf.SPFSyntaxError(msg: str, data: dict | None = None)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

exception checkdmarc.spf.SPFTooManyDNSLookups(*args, **kwargs)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

exception checkdmarc.spf.SPFTooManyVoidDNSLookups(*args, **kwargs)[source]
Parameters:
  • msg (str) – The error message

  • data (dict) – A dictionary of data to include in the output

exception checkdmarc.spf.UndecodableCharactersInTXTRecord[source]

Raised when a TXT record contains one or more undecodable characters

checkdmarc.spf.check_spf(domain: str, *, parked: bool = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) dict[source]

Returns a dictionary with a parsed SPF record or an error.

Parameters:
  • domain (str) – A domain name

  • parked (bool) – The domain is parked

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A dict with the following keys:
  • record - The SPF record string

  • parsed - The parsed SPF record

  • dns_lookups - The number of DNS lookups

  • void_dns_lookups - The number of void DNS lookups

  • valid - True

  • warnings - A list of warnings

If a DNS error occurs, the dictionary will have the following keys:
  • error - The error message

  • valid - False

Return type:

dict

checkdmarc.spf.get_spf_record(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) ParsedSPFRecordSuccess | ParsedSPFRecordError[source]

Retrieves and parses an SPF record

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – Number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

The parsed SPF record results

Return type:

dict

Raises:
checkdmarc.spf.parse_spf_record(record: str, domain: str, *, ignore_too_many_lookups: bool = False, parked: bool = False, seen: list | None = None, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, recursion: list[str] | None = None, timeout: float = 2.0, retries: int = 0, syntax_error_marker: str = '➞', _include_cache: dict[str, ParsedSPFRecordSuccess | ParsedSPFRecordError] | None = None, _included: bool = False) ParsedSPFRecordSuccess | ParsedSPFRecordError[source]

Parses an SPF record, including resolving a, mx, and include mechanisms

Parameters:
  • record (str) – An SPF record

  • domain (str) – The domain that the SPF record came from

  • parked (bool) – Indicates if a domain has been parked

  • ignore_too_many_lookups (bool) – Do not raise an exception for too many lookups

  • seen (list) – A list of domains seen in past loops

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • recursion (list) – A list of domains used in recursion

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

  • syntax_error_marker (str) – The marker for pointing out syntax errors

  • _included (bool) – Internal flag: this record was reached by following an include

Returns:

A dict with the following keys:
  • record - The SPF record string

  • dns_lookups - Number of DNS lookups required by the record

  • void_dns_lookups - The number of void DNS lookups

  • parsed - A dict of parsed SPF record values

  • warnings - A list of warnings

Return type:

dict

Raises:
checkdmarc.spf.ptr_match(ip_address: str, domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) bool[source]

Performs a ptr mechanism check.

Parameters:
  • ip_address (str) – The IP address of the sending host

  • domain (str) – The domain name to match against

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

The result of the check

Return type:

bool

Raises:

checkdmarc.utils.DNSException

checkdmarc.spf.query_spf_record(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, quoted_txt_segments: bool = False, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) SPFQueryResults[source]

Queries DNS for an SPF record

Parameters:
  • domain (str) – A domain name

  • quoted_txt_segments (bool) – Retain quotes around TXT segments

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A dict with the following keys:
  • record - The SPF record string

  • warnings - A list of warnings

Return type:

dict

Raises:

checkdmarc.utils

DNS utility functions

exception checkdmarc.utils.DNSException(error)[source]

Raised when a general DNS error occurs

exception checkdmarc.utils.DNSExceptionNXDOMAIN(error)[source]

Raised when an NXDOMAIN DNS error (RCODE:3) occurs

class checkdmarc.utils.MXHost[source]

A Mail Exchange host

hostname and preference come from the MX record itself (get_mx_records()); the remaining fields are added by checkdmarc.smtp.get_mx_hosts()tls and starttls only when TLS testing is not skipped.

class checkdmarc.utils.MXRecord[source]

One MX record: a hostname and its preference

class checkdmarc.utils.MXRecordSet[source]

Everything learned from a domain’s MX lookup: the usable hosts, warnings about problems in the records themselves, and whether the domain published a null MX record (RFC 7505) declaring that it does not accept mail.

class checkdmarc.utils.NameserverResultError[source]
class checkdmarc.utils.NameserverResultOk[source]
checkdmarc.utils.get_a_records(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) list[str][source]

Queries DNS for A and AAAA records

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A sorted list of IPv4 and IPv6 addresses

Return type:

list

Raises:

checkdmarc.DNSException

checkdmarc.utils.get_base_domain(domain: str) str[source]

Gets the base domain name for the given domain

Note

Results are based on a list of public domain suffixes at https://publicsuffix.org/list/public_suffix_list.dat.

Parameters:

domain (str) – A domain or subdomain

Returns:

The base domain of the given domain

Return type:

str

checkdmarc.utils.get_mx_record_set(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) MXRecordSet[source]

Queries DNS for a domain’s Mail Exchange records, validates them, and reports what the records mean

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A dictionary with the following keys:

  • hosts - A list of dicts; each containing a preference integer and a hostname

  • warnings - Warnings about the MX records themselves

  • null_mx - True when the domain publishes only a null MX record (0 .), meaning it explicitly does not accept mail (RFC 7505)

  • record_count - The number of MX records in the DNS answer, including null and malformed records that do not become hosts entries

Return type:

dict

Raises:

checkdmarc.DNSException

checkdmarc.utils.get_mx_records(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) list[MXHost][source]

Queries DNS for a list of Mail Exchange hosts

Use get_mx_record_set() instead when the warnings about the records or the null MX status are needed; this function returns only the hosts (an empty list for a domain with a null MX record).

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A list of dicts; each containing a preference

integer and a hostname

Return type:

list

Raises:

checkdmarc.DNSException

checkdmarc.utils.get_nameservers(domain: str, *, approved_nameservers: Sequence[str | Nameserver] | None = None, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) NameserverResultOk[source]

Gets a list of nameservers for a given domain

Parameters:
  • domain (str) – A domain name

  • approved_nameservers (list) – A list of approved nameserver substrings

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A dictionary with the following keys:
  • hostnames - A list of nameserver hostnames

  • warnings - A list of warnings

Return type:

dict

checkdmarc.utils.get_reverse_dns(ip_address: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) list[str][source]

Queries for an IP address’s reverse DNS hostname(s)

Parameters:
  • ip_address (str) – An IPv4 or IPv6 address

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A list of reverse DNS hostnames

Return type:

list

Raises:

checkdmarc.DNSException

checkdmarc.utils.get_soa_record(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) str[source]

Queries DNS for an SOA record

Parameters:
  • domain (str) – A domain name

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

An SOA record

Return type:

str

Raises:

checkdmarc.DNSException

checkdmarc.utils.get_txt_records(domain: str, *, nameservers: Sequence[str | Nameserver] | None = None, quoted_txt_segments: bool = False, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0) list[str][source]

Queries DNS for TXT records

Parameters:
  • domain (str) – A domain name

  • quoted_txt_segments (bool) – Preserve quotes in TXT records

  • nameservers (list) – A list of nameservers to query

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – number of seconds to wait for an answer from DNS

  • retries (int) – The number of times to retry on timeout or other transient errors

Returns:

A list of TXT records

Return type:

list

Raises:

checkdmarc.DNSException

checkdmarc.utils.normalize_domain(domain: str) str[source]

Normalize an input domain by removing zero-width characters and lowercasing it

Parameters:

domain (str) – A domain or subdomain

Returns:

A normalized domain

Return type:

str

checkdmarc.utils.query_dns(domain: str, record_type: str, *, quoted_txt_segments: bool = False, nameservers: Sequence[str | Nameserver] | None = None, resolver: Resolver | None = None, timeout: float = 2.0, retries: int = 0, _attempt: int = 0, cache: ExpiringDict | None = None) list[str][source]

Queries DNS

Parameters:
  • domain (str) – The domain or subdomain to query about

  • record_type (str) – The record type to query for

  • quoted_txt_segments (bool) – Preserve quotes in TXT records

  • nameservers (list) – A list of one or more nameservers to use. Defaults to the system-configured resolvers (/etc/resolv.conf on Linux/macOS, the OS resolver on Windows). For reliability, pass RECOMMENDED_DNS_NAMESERVERS or your own mix of public resolvers so failover happens when one provider’s path is slow or broken. Each entry is an IP address (DNS over UDP/TCP port 53), an https:// URL (DNS over HTTPS, honoring the HTTP_PROXY/HTTPS_PROXY/NO_PROXY and SSL_CERT_FILE environment variables), or tls://ip[:port][#hostname] (DNS over TLS, port 853 by default, with the optional #hostname naming the server’s TLS certificate identity).

  • resolver (dns.resolver.Resolver) – A resolver object to use for DNS requests

  • timeout (float) – Overall DNS lifetime budget in seconds per configured nameserver. Per-query UDP attempts are capped at min(1.0, timeout) so dnspython retries within the lifetime on transient UDP packet loss (mirroring dig’s default +tries=3 behavior); with multiple nameservers configured this same cap also makes a slow or broken nameserver fall through to the next quickly

  • retries (int) – Number of times to retry the whole query after a timeout or other transient error (LifetimeTimeout, NoNameservers, OSError). Failover between configured nameservers happens within each attempt.

  • cache (ExpiringDict) – Cache storage

Returns:

A list of answers

Return type:

list