### get_nameservers Source: https://domainaware.github.io/checkdmarc/api.html Gets a list of nameservers for a given domain. ```APIDOC ## get_nameservers ### Description Gets a list of nameservers for a given domain. ### Parameters #### Query Parameters - **domain** (str) - Required - A domain name - **approved_nameservers** (list) - Optional - A list of approved nameserver substrings - **nameservers** (list) - Optional - A list of nameservers to query - **resolver** (dns.resolver.Resolver) - Optional - A resolver object to use for DNS requests - **timeout** (float) - Optional - number of seconds to wait for a record from DNS - **timeout_retries** (int) - Optional - The number of times to reattempt a query after a timeout ### Response - **Returns** (dict) - A dictionary with keys 'hostnames' (list) and 'warnings' (list) ``` -------------------------------- ### Install Latest Development Checkdmarc Release from GitHub Source: https://domainaware.github.io/checkdmarc/_sources/installation.md.txt Install the most recent development version of checkdmarc directly from its GitHub repository using pip3. This is useful for testing the latest features. ```text pip3 install -U git+https://github.com/domainaware/checkdmarc.git ``` -------------------------------- ### Install Python 3 Pip on Debian/Ubuntu Source: https://domainaware.github.io/checkdmarc/_sources/installation.md.txt Use this command to install the pip package manager for Python 3 on Debian or Ubuntu systems. This is a prerequisite for installing checkdmarc. ```text sudo apt-get install python3-pip ``` -------------------------------- ### GET /dns/soa_record Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Fetches the SOA (Start of Authority) record for a domain. Allows specifying nameservers and custom resolver settings. ```APIDOC ## GET /dns/soa_record ### Description Queries DNS for the SOA record of a given domain. ### Method GET ### Endpoint /dns/soa_record ### Parameters #### Query Parameters - **domain** (str) - Required - The domain name to query. - **nameservers** (list[str | Nameserver]) - Optional - A list of nameservers to query. - **resolver** (dns.resolver.Resolver) - Optional - A custom resolver object. - **timeout** (float) - Optional - Timeout in seconds for DNS queries. Defaults to 2.0. - **timeout_retries** (int) - Optional - Number of retries after a timeout. Defaults to 2. ### Response #### Success Response (200) - **soa_record** (str) - The SOA record for the domain. #### Response Example ```json { "soa_record": "ns1.example.com hostmaster.example.com 2023102700 7200 3600 1209600 3600" } ``` ### Errors - **DNSExceptionNXDOMAIN**: The domain does not exist. - **DNSException**: No SOA record found or other DNS errors. ``` -------------------------------- ### GET /dns/nameservers Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Retrieves the nameservers for a domain, with options to filter by approved nameservers and configure DNS query parameters. ```APIDOC ## GET /dns/nameservers ### Description Retrieves a list of nameservers for a given domain. ### Method GET ### Endpoint /dns/nameservers ### Parameters #### Query Parameters - **domain** (str) - Required - The domain name to query. - **approved_nameservers** (list[str | Nameserver]) - Optional - A list of approved nameserver substrings to filter against. - **nameservers** (list[str | Nameserver]) - Optional - A list of nameservers to query. - **resolver** (dns.resolver.Resolver) - Optional - A custom resolver object. - **timeout** (float) - Optional - Timeout in seconds for DNS queries. Defaults to 2.0. - **timeout_retries** (int) - Optional - Number of retries after a timeout. Defaults to 2. ### Response #### Success Response (200) - **hostnames** (list[str]) - A list of nameserver hostnames. - **warnings** (list[str]) - A list of warnings, e.g., for unapproved nameservers. #### Response Example ```json { "hostnames": [ "ns1.example.com", "ns2.example.com" ], "warnings": [ "Unapproved nameserver: ns3.other.com" ] } ``` ### Errors - **DNSExceptionNXDOMAIN**: The domain does not exist. - **DNSException**: Other DNS query errors. ``` -------------------------------- ### Example JSON Output Source: https://domainaware.github.io/checkdmarc/cli.html Represents the structured data returned by checkdmarc for a domain, including DNS, SPF, and DMARC records. ```json { "domain": "proton.me", "base_domain": "proton.me", "dnssec": true, "soa": { "record": "ns1.proton.me. support.proton.me. 2025091157 1200 144 1814400 7200", "values": { "primary_nameserver": "ns1.proton.me", "rname_email_address": "support@proton.me", "serial": 2025091157, "refresh": 1200, "retry": 144, "expire": 1814400, "minimum": 7200 } }, "ns": { "hostnames": [ "ns1.proton.me", "ns2.proton.me", "ns3.proton.me" ], "warnings": [] }, "mx": { "hosts": [ { "preference": 10, "hostname": "mail.protonmail.ch", "addresses": [ "176.119.200.128", "185.205.70.128", "185.70.42.128" ], "dnssec": true, "tlsa": [ "3 1 1 6111a5698d23c89e09c36ff833c1487edc1b0c841f87c49dae8f7a09e11e979e", "3 1 1 76bb66711da416433ca890a5b2e5a0533c6006478f7d10a4469a947acc8399e1" ] }, { "preference": 20, "hostname": "mailsec.protonmail.ch", "addresses": [ "176.119.200.129", "185.205.70.129", "185.70.42.129" ], "dnssec": true, "tlsa": [ "3 1 1 6111a5698d23c89e09c36ff833c1487edc1b0c841f87c49dae8f7a09e11e979e", "3 1 1 76bb66711da416433ca890a5b2e5a0533c6006478f7d10a4469a947acc8399e1" ] } ], "warnings": [] }, "mta_sts": { "valid": true, "id": "190906205100Z", "policy": { "version": "STSv1", "mode": "enforce", "max_age": 604800, "mx": [ "mail.protonmail.ch", "mailsec.protonmail.ch" ] }, "warnings": [] }, "spf": { "record": "v=spf1 include:_spf.protonmail.ch ~all", "valid": true, "dns_lookups": 2, "void_dns_lookups": 0, "warnings": [], "parsed": { "mechanisms": [ { "mechanism": "include", "value": "_spf.protonmail.ch", "record": "v=spf1 ip4:185.70.40.0/24 ip4:185.70.41.0/24 ip4:185.70.43.0/24 ip4:79.135.106.0/24 ip4:79.135.107.0/24 ip4:109.224.244.0/24 include:_spf2.protonmail.ch ~all", "dns_lookups": 2, "void_dns_lookups": 0, "parsed": { "mechanisms": [ { "mechanism": "ip4", "value": "185.70.40.0/24", "action": "pass" }, { "mechanism": "ip4", "value": "185.70.41.0/24", "action": "pass" }, { "mechanism": "ip4", "value": "185.70.43.0/24", "action": "pass" }, { "mechanism": "ip4", "value": "79.135.106.0/24", "action": "pass" }, { "mechanism": "ip4", "value": "79.135.107.0/24", "action": "pass" }, { "mechanism": "ip4", "value": "109.224.244.0/24", "action": "pass" }, { "mechanism": "include", "value": "_spf2.protonmail.ch", "record": "v=spf1 ip4:85.9.206.169 ip4:85.9.210.45 ip4:188.165.51.139 ip4:57.129.93.249 ~all", "dns_lookups": 1, "void_dns_lookups": 0, "parsed": { "mechanisms": [ { "mechanism": "ip4", "value": "85.9.206.169", "action": "pass" }, { "mechanism": "ip4", "value": "85.9.210.45", "action": "pass" }, { "mechanism": "ip4", "value": "188.165.51.139", "action": "pass" }, { "mechanism": "ip4", "value": "57.129.93.249", "action": "pass" } ], "redirect": null, "exp": null, "all": "softfail" }, "warnings": [] } ], "redirect": null, "exp": null, "all": "softfail" }, "warnings": [] } ], "redirect": null, "exp": null, "all": "softfail" } }, "dmarc": { "record": "v=DMARC1; p=quarantine; fo=1; aspf=s; adkim=s;", "valid": true, "location": "proton.me", "warnings": [ "rua tag (destination for aggregate reports) not found." ], "tags": { "v": { "value": "DMARC1", "explicit": true }, "p": { ``` -------------------------------- ### checkdmarc.soa Module Source: https://domainaware.github.io/checkdmarc/_sources/api.md.txt Documentation for the SOA (Start of Authority) record related functions within checkdmarc. ```APIDOC ## checkdmarc.soa ### Description Provides functionality related to SOA record retrieval and analysis. ### Method N/A (Module Documentation) ### Endpoint N/A (Module Documentation) ### Parameters N/A ### Request Example N/A ### Response N/A ``` -------------------------------- ### Get TXT Records Source: https://domainaware.github.io/checkdmarc/api.html Queries DNS for TXT records associated with a given domain. ```APIDOC ## GET /utils/get_txt_records ### Description Queries DNS for TXT records for a specified domain. ### Method GET ### Endpoint /utils/get_txt_records ### Parameters #### Query Parameters - **domain** (str) - Required - The domain name to query. - **quoted_txt_segments** (bool) - Optional - Preserve quotes in TXT records. Defaults to False. - **nameservers** (list[str | Nameserver]) - Optional - A list of nameservers to query. - **resolver** (dns.resolver.Resolver) - Optional - A resolver object to use for DNS requests. - **timeout** (float) - Optional - Number of seconds to wait for an answer from DNS. Defaults to 2.0. - **timeout_retries** (int) - Optional - The number of times to reattempt a query after a timeout. Defaults to 2. ### Response #### Success Response (200) - **records** (list[str]) - A list of TXT records found. #### Error Response (400) - **error** (str) - Description of the error. ### Raises - **checkdmarc.DNSException** - If a DNS query fails. ``` -------------------------------- ### GET /mx-records Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/smtp.html Retrieves MX hostnames, their associated IP addresses, and security status for a given domain. ```APIDOC ## GET /mx-records ### Description Retrieves MX hostnames and their addresses for a specified domain, including DNSSEC status and TLSA records. ### Method GET ### Endpoint /mx-records ### Parameters #### Query Parameters - **domain** (str) - Required - A domain name - **skip_tls** (bool) - Optional - Skip STARTTLS testing - **approved_hostnames** (list) - Optional - A list of approved MX hostname substrings - **mta_sts_mx_patterns** (list) - Optional - A list of MX patterns from MTA-STS - **parked** (bool) - Optional - Indicates that the domains are parked - **nameservers** (list) - Optional - A list of nameservers to query - **timeout** (float) - Optional - Number of seconds to wait for a record from DNS ### Response #### Success Response (200) - **hosts** (list) - A list of dicts containing hostname, dnssec, addresses, and tlsa records - **warnings** (list) - A list of MX resolution warnings ``` -------------------------------- ### Get Reverse DNS Hostnames Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Queries for reverse DNS hostnames (PTR records) for a given IP address. Returns an empty list if the domain does not exist. ```python def get_reverse_dns( ip_address: str, *, nameservers: Optional[Sequence[str | Nameserver]] = None, resolver: Optional[dns.resolver.Resolver] = None, timeout: float = 2.0, timeout_retries: int = 2, ) -> list[str]: """ Queries for an IP addresses reverse DNS hostname(s) Args: 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 timeout_retries (int): The number of times to reattempt a query after a timeout Returns: list: A list of reverse DNS hostnames Raises: :exc:`checkdmarc.DNSException` """ try: name = str(dns.reversename.from_address(ip_address)) logging.debug(f"Getting PTR records for {ip_address}") hostnames = query_dns( name, "PTR", nameservers=nameservers, resolver=resolver, timeout=timeout, timeout_retries=timeout_retries, ) except dns.resolver.NXDOMAIN: return [] except Exception as error: ``` -------------------------------- ### Get Domain Nameservers Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Retrieves a list of nameservers for a given domain. It can optionally filter these nameservers against a list of approved substrings. Handles NXDOMAIN and NoAnswer exceptions. Supports custom nameservers, resolvers, and timeouts. ```python def get_nameservers( domain: str, *, approved_nameservers: Optional[Sequence[str | Nameserver]] = None, nameservers: Optional[Sequence[str | Nameserver]] = None, resolver: Optional[dns.resolver.Resolver] = None, timeout: float = 2.0, timeout_retries: int = 2, ) -> dict: """ Gets a list of nameservers for a given domain Args: 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 a record from DNS timeout_retries (int): The number of times to reattempt a query after a timeout Returns: dict: A dictionary with the following keys: - ``hostnames`` - A list of nameserver hostnames - ``warnings`` - A list of warnings """ logging.debug(f"Getting NS records on {domain}") warnings = [] ns_records = [] try: ns_records = query_dns( domain, "NS", nameservers=nameservers, resolver=resolver, timeout=timeout, timeout_retries=timeout_retries, ) except dns.resolver.NXDOMAIN: raise DNSExceptionNXDOMAIN("The domain does not exist.") except dns.resolver.NoAnswer: pass except Exception as error: raise DNSException(error) if approved_nameservers: approved_nameservers = list(map(lambda h: str(h).lower(), approved_nameservers)) for nameserver in ns_records: if approved_nameservers: approved = False for approved_nameserver in approved_nameservers: if str(approved_nameserver).lower() in nameserver.lower(): approved = True break if not approved: warnings.append(f"Unapproved nameserver: {nameserver}") ``` -------------------------------- ### Get MX Records Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Queries DNS for a list of Mail Exchange (MX) hosts for a given domain. ```APIDOC ## GET /api/mx_records ### Description Queries DNS for a list of Mail Exchange hosts for a specified domain. ### Method GET ### Endpoint /api/mx_records ### Parameters #### Query Parameters - **domain** (str) - Required - The domain name to query for MX records. - **nameservers** (list[str | Nameserver]) - Optional - A list of nameservers to query. Defaults to system resolvers. - **resolver** (dns.resolver.Resolver) - Optional - A custom resolver object to use for DNS requests. - **timeout** (float) - Optional - The number of seconds to wait for a DNS response. Defaults to 2.0. - **timeout_retries** (int) - Optional - The number of times to reattempt a query after a timeout. Defaults to 2. ### Response #### Success Response (200) - **hosts** (list[dict]) - A list of dictionaries, where each dictionary contains: - **preference** (int) - The preference value for the MX record. - **hostname** (str) - The hostname of the mail exchange server. #### Response Example ```json { "hosts": [ {"preference": 10, "hostname": "mail.example.com"}, {"preference": 20, "hostname": "backupmail.example.com"} ] } ``` #### Error Handling - **checkdmarc.DNSExceptionNXDOMAIN**: Raised if the domain does not exist. - **checkdmarc.DNSException**: Raised for other DNS-related errors. ``` -------------------------------- ### Get A and AAAA Records Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Queries DNS for A and AAAA records for a given domain. Handles NXDOMAIN and NoAnswer exceptions, and raises a general DNSException for other errors. ```python def get_a_records( domain: str, *, nameservers: Optional[Sequence[str | Nameserver]] = None, resolver: Optional[dns.resolver.Resolver] = None, timeout: float = 2.0, timeout_retries: int = 2, ) -> list[str]: """ Queries DNS for A and AAAA records Args: 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 Returns: list: A sorted list of IPv4 and IPv6 addresses Raises: :exc:`checkdmarc.DNSException` """ qtypes = ["A", "AAAA"] addresses = [] for qt in qtypes: try: logging.debug(f"Getting {qt} records for {domain}") addresses += query_dns( domain, qt, nameservers=nameservers, resolver=resolver, timeout=timeout, timeout_retries=timeout_retries, ) except dns.resolver.NXDOMAIN: raise DNSExceptionNXDOMAIN("The domain does not exist.") except dns.resolver.NoAnswer: # Sometimes a domain will only have A or AAAA records, but not both pass except Exception as error: raise DNSException(error) addresses = sorted(addresses) return addresses ``` -------------------------------- ### Configure PolicyBuilder for X.509 Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/bimi.html Sets up extension policies and builds a client verifier using the PolicyBuilder class. ```python _ee_policy = ( ExtensionPolicy.permit_all() .require_present(x509.SubjectAlternativeName, Criticality.AGNOSTIC, None) .may_be_present(x509.ExtendedKeyUsage, Criticality.AGNOSTIC, None) ) _ca_policy = ( ExtensionPolicy.permit_all() .require_present(x509.BasicConstraints, Criticality.AGNOSTIC, None) .may_be_present(x509.ExtendedKeyUsage, Criticality.AGNOSTIC, None) ) _builder = ( PolicyBuilder() .store(_store) .extension_policies(ee_policy=_ee_policy, ca_policy=_ca_policy) .max_chain_depth(5) ) _verifier = _builder.build_client_verifier() ``` -------------------------------- ### Initialize Certificate Store Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/bimi.html Loads PEM-encoded X.509 certificates from a file into a certificate store. This configuration ensures that certificates marked critical by the issuer but not processable by OpenSSL are still considered valid. ```python _mvaca_path = str(files(checkdmarc.resources).joinpath("MVACAs.pem")) # Load the certificates included in MVACAs.pem into a certificate store with open(_mvaca_path, "rb") as pems: _store = Store(load_pem_x509_certificates(pems.read())) # Do not consider certificate invalid if a certificate extension marked critical # by the issuer cannot be processed by OpenSSL. ``` -------------------------------- ### Install Latest Stable Checkdmarc Release Source: https://domainaware.github.io/checkdmarc/_sources/installation.md.txt Install or upgrade to the latest stable version of the checkdmarc package using pip3. Ensure Python 3.10 or later is installed. ```text pip3 install -U checkdmarc ``` -------------------------------- ### Return Hostname Records Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Returns a dictionary containing hostnames and associated warnings. ```python return {"hostnames": ns_records, "warnings": warnings} ``` -------------------------------- ### checkdmarc.smtp.test_starttls Source: https://domainaware.github.io/checkdmarc/api.html Attempts to connect to an SMTP server and validates STARTTLS support. Returns `True` if STARTTLS is supported, otherwise raises an `SMTPError`. ```APIDOC ## test_starttls ### Description Attempt to connect to an SMTP server and validate STARTTLS support. ### Method N/A (Function) ### Endpoint N/A (Function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **hostname** (_str_) – The hostname * **ssl_context** (_SSLContext | None_) – A SSL context * **cache** (_ExpiringDict | None_) – Cache storage * **timeout** (_float_) – timeout in seconds ### Request Example None ### Response #### Success Response (200) * **True** (bool) - Indicates STARTTLS is supported. #### Error Response * **checkdmarc.smtp.SMTPError** – SMTP connection failed. #### Response Example ```python True ``` ``` -------------------------------- ### Check NS API Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc.html Retrieves nameserver information and associated warnings for a given domain. ```APIDOC ## GET /api/domains/{domain}/ns ### Description Fetches the nameserver records and any associated warnings for a specified domain. ### Method GET ### Endpoint /api/domains/{domain}/ns ### Parameters #### Path Parameters - **domain** (str) - Required - The domain name to check. #### Query Parameters - **approved_nameservers** (list[str], optional) - A list of approved nameserver substrings. - **nameservers** (list[str], optional) - A list of specific nameservers to query. - **resolver** (object, optional) - A custom DNS resolver object. - **timeout** (float, optional) - Timeout in seconds for DNS queries. Defaults to 2.0. - **timeout_retries** (int, optional) - Number of retries for timed-out DNS queries. Defaults to 2. ### Response #### Success Response (200) - **hostnames** (list[str]) - A list of nameserver hostnames. - **warnings** (list[str]) - A list of warnings encountered during the check. - **error** (str) - An error message if a DNS error occurred. #### Response Example ```json { "hostnames": ["ns1.example.com.", "ns2.example.com."], "warnings": [] } ``` #### Error Response Example ```json { "hostnames": [], "error": "DNS query failed: SERVFAIL" } ``` ``` -------------------------------- ### checkdmarc.dmarc.get_dmarc_tag_description Source: https://domainaware.github.io/checkdmarc/api.html Get the name, default value, and description for a DMARC tag. ```APIDOC ## checkdmarc.dmarc.get_dmarc_tag_description ### Description Get the name, default value, and description for a DMARC tag, and/or a description for a tag value. ### Parameters #### Query Parameters - **tag** (str) - Required - A DMARC tag - **value** (str|list) - Optional - An optional value ### Response #### Success Response (200) - **name** (str) - The tag name - **default** (str) - The tag's default value - **description** (str) - A description of the tag or value ``` -------------------------------- ### check_ns Source: https://domainaware.github.io/checkdmarc/api.html Returns a dictionary of nameservers and warnings or a dictionary with an error message for a given domain. ```APIDOC ## check_ns ### Description Returns a dictionary of nameservers and warnings or a dictionary with an error message for a given domain. ### Parameters #### Request Body - **domain** (str) - Required - A domain name - **approved_nameservers** (list) - Optional - A list of approved nameserver substrings - **nameservers** (list) - Optional - A list of nameservers to query - **resolver** (dns.resolver.Resolver) - Optional - A resolver object to use for DNS requests - **timeout** (float) - Optional - Number of seconds to wait for a record from DNS ### Response #### Success Response (200) - **hostnames** (list) - A list of nameserver hostnames - **warnings** (list) - A list of warnings - **error** (str) - An error message (if a DNS error occurs) ``` -------------------------------- ### GET /dmarc/tags Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/dmarc.html Retrieves metadata and descriptions for a specific DMARC tag and its optional value. ```APIDOC ## GET /dmarc/tags ### Description Returns the name, default value, and description for a given DMARC tag, and optionally provides a description for a specific tag value. ### Parameters #### Request Body - **tag** (string) - Required - A DMARC tag. - **value** (string/list) - Optional - An optional value to get a description for. ### Response #### Success Response (200) - **name** (string) - The tag name. - **default** (string) - The tag's default value. - **description** (string) - A description of the tag or value. ``` -------------------------------- ### GET /check_mta_sts Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/mta_sts.html Checks the MTA-STS policy for a specific domain using DNS resolution. ```APIDOC ## GET /check_mta_sts ### Description Retrieves and validates the MTA-STS policy for a given domain. ### Method GET ### Endpoint /check_mta_sts ### Parameters #### Query Parameters - **domain** (string) - Required - The domain name to check. - **nameservers** (list) - Optional - A list of nameservers to query. - **resolver** (object) - Optional - A custom DNS resolver object. - **timeout** (float) - Optional - Seconds to wait for DNS response. - **timeout_retries** (int) - Optional - Number of retries for DNS queries. ### Response #### Success Response (200) - **id** (string) - The SIS-MTA DNS record ID. - **policy** (object) - The parsed MTA-STS policy. - **valid** (boolean) - Indicates if the policy is valid. - **warnings** (list) - A list of warnings encountered. ``` -------------------------------- ### Validate SMTP STARTTLS Support Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/smtp.html Attempts to connect to an SMTP server to verify if STARTTLS is supported, with support for SSL contexts and caching. ```python def test_starttls( hostname: str, *, ssl_context: Optional[ssl.SSLContext] = None, cache: Optional[ExpiringDict] = None, timeout: float = 5, ) -> bool: """ Attempt to connect to an SMTP server and validate STARTTLS support Args: hostname (str): The hostname cache (ExpiringDict): Cache storage ssl_context: A SSL context Returns: bool: True if STARTTLS supported Raises: checkdmarc.smtp.SMTPError: SMTP connection failed """ hostname = normalize_domain(hostname) starttls = False if isinstance(cache, ExpiringDict): cached_result = cache.get(hostname) if isinstance(cached_result, dict): if cached_result["error"] is not None: raise SMTPError(cached_result["error"]) return cached_result["starttls"] if ssl_context is None: ssl_context = ssl.create_default_context() logging.debug(f"Testing STARTTLS on {hostname}") try: with smtplib.SMTP(hostname, timeout=timeout) as server: server.ehlo_or_helo_if_needed() if server.has_extn("starttls"): server.starttls(context=ssl_context) server.ehlo() starttls = True if cache: cache[hostname] = {"starttls": starttls, "error": None} return starttls except socket.gaierror: error = "DNS resolution failed" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except ConnectionRefusedError: error = "Connection refused" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except ConnectionResetError: error = "Connection reset" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except ConnectionAbortedError: error = "Connection aborted" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except TimeoutError: error = "Connection timed out" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except BlockingIOError as e: error = e.__str__() if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except ssl.SSLError as e: error = f"SSL error: {e}" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except smtplib.SMTPConnectError as e: message = e.__str__() error_code = int(message.lstrip("(").split(",")[0]) if error_code == 554: message = " SMTP error code 554 - Not allowed" else: message = f" SMTP error code {error_code}" error = f"Could not connect: {message}" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except smtplib.SMTPHeloError as e: error = f"HELO error: {e}" if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except smtplib.SMTPException as e: error = e.__str__() try: error_code = error.lstrip("(").split(",")[0] error = f"SMTP error code {error_code}" except ValueError: pass if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except OSError as e: error = e.__str__() if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) except Exception as e: error = e.__str__() if cache: cache[hostname] = {"starttls": False, "error": error} raise SMTPError(error) ``` -------------------------------- ### get_base_domain Source: https://domainaware.github.io/checkdmarc/api.html Gets the base domain name for the given domain based on public suffix lists. ```APIDOC ## get_base_domain ### Description Gets the base domain name for the given domain. ### Parameters #### Query Parameters - **domain** (str) - Required - A domain or subdomain ### Response - **Returns** (str) - The base domain of the given domain ``` -------------------------------- ### Download MTA-STS Policy Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/mta_sts.html Retrieves an MTA-STS policy file from a domain's well-known location. Requires an active network connection and handles HTTP timeouts. ```python def download_mta_sts_policy( domain: str, *, http_timeout: float = DEFAULT_HTTP_TIMEOUT ) -> DownloadedMTASTSPolicy: """ Downloads a domains MTA-HTS policy Args: domain (str): A domain name http_timeout (float): HTTP timeout in seconds Returns: dict: a ``dict`` with the following keys: - ``policy`` - The unparsed policy string - ``warnings`` - A list of any warning conditions found Raises: :exc:`checkdmarc.mta_sts.MTASTSPolicyDownloadError` """ warnings = [] headers = {"User-Agent": USER_AGENT} session = requests.Session() session.headers = headers # pyright: ignore[reportAttributeAccessIssue] expected_content_type = "text/plain" url = f"https://mta-sts.{domain}/.well-known/mta-sts.txt" logging.debug(f"Attempting to download HTA-MTS policy from {url}") try: response = session.get(url, timeout=http_timeout) response.raise_for_status() ``` -------------------------------- ### Check DMARC Record with Options Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/dmarc.html Provides a comprehensive check for a DMARC record, allowing configuration for parked domains, tag descriptions, and ignoring unrelated records. Handles DNS and parsing errors. ```python try: dmarc_query = query_dmarc_record( domain, ignore_unrelated_records=ignore_unrelated_records, nameservers=nameservers, resolver=resolver, timeout=timeout, timeout_retries=timeout_retries, ) except DMARCError as error: error_results: DMARCErrorResults = { "record": None, "location": None, "valid": False, "error": str(error), } return error_results try: parsed_dmarc_record = parse_dmarc_record( dmarc_query["record"], dmarc_query["location"], parked=parked, include_tag_descriptions=include_dmarc_tag_descriptions, ignore_unrelated_records=ignore_unrelated_records, nameservers=nameservers, resolver=resolver, timeout=timeout, timeout_retries=timeout_retries, ) combined_warnings = dmarc_query["warnings"] + parsed_dmarc_record["warnings"] dmarc_results: DMARCResults = { "record": dmarc_query["record"], "location": dmarc_query["location"], "valid": True, "warnings": combined_warnings, "tags": parsed_dmarc_record["tags"], } return dmarc_results except DMARCError as error: error_results: DMARCErrorResults = { "record": dmarc_query["record"], "location": dmarc_query["location"], "valid": False, "error": str(error), } if hasattr(error, "data") and error.data: if "target" in error.data: error_results["target"] = error.data["target"] return error_results ``` -------------------------------- ### GET /dmarc/record Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/dmarc.html Queries a domain for a DMARC record, performing a DNS tree walk if necessary to discover the policy. ```APIDOC ## GET /dmarc/record ### Description Queries the DNS for a DMARC record associated with a domain. If no record is found at the domain, it performs a DMARCbis DNS tree walk to find a policy at the parent domain. ### Parameters #### Request Body - **domain** (string) - Required - The domain to check. - **nameservers** (list) - Optional - A list of nameservers to query. - **resolver** (dns.resolver.Resolver) - Optional - A resolver object to use for DNS requests. - **timeout** (float) - Optional - Number of seconds to wait for a record from DNS. - **timeout_retries** (int) - Optional - The number of times to reattempt a query after a timeout. - **ignore_unrelated_records** (bool) - Optional - Ignore unrelated TXT records. ### Response #### Success Response (200) - **record** (string) - The unparsed DMARC record string. - **location** (string) - The domain where the record was found. - **warnings** (list) - Warning conditions found during the check. ``` -------------------------------- ### Handle SPF Void DNS Lookup Exception Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/spf.html Increments void DNS lookup counters and records a failed mechanism when encountering DNS exceptions like NXDOMAIN or missing records. ```python except (_SPFWarning, DNSException) as warning: if isinstance(warning, (_SPFMissingRecords, DNSExceptionNXDOMAIN)): mechanism_void_dns_lookups += 1 total_void_dns_lookups += 1 failed_mechanism: SPFDNSLookupMechanism = { "action": action, "mechanism": mechanism, "value": value, "dns_lookups": 1, "void_dns_lookups": 1, } parsed["mechanisms"].append(failed_mechanism) if total_void_dns_lookups > 2: raise SPFTooManyVoidDNSLookups( "Parsing the SPF record has " f"{total_void_dns_lookups}/2 maximum void DNS " "lookups (RFC 7208 § 4.6.4)", ``` -------------------------------- ### Get DNSKEY Records Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/dnssec.html Retrieves the DNSKEY RRSet for a given domain, with options for specifying nameservers, timeout, and caching. ```APIDOC ## GET /dnskey ### Description Retrieves the DNSKEY RRSet for a given domain. This function can query specific nameservers and has configurable timeouts and caching mechanisms. ### Method GET ### Endpoint /dnskey ### Parameters #### Query Parameters - **domain** (str) - Required - The domain for which to retrieve DNSKEY records. - **nameservers** (list[str | Nameserver]) - Optional - A list of nameservers to query. Defaults to the system's default resolvers. - **timeout** (float) - Optional - The timeout in seconds for the DNS query. Defaults to 2.0 seconds. - **cache** (ExpiringDict) - Optional - A cache object to store and retrieve DNSKEY records. Defaults to a global DNSKEY_CACHE. ### Request Example ```json { "domain": "example.com", "nameservers": ["8.8.8.8", "8.8.4.4"], "timeout": 5.0 } ``` ### Response #### Success Response (200) - **dict** - A dictionary containing the DNSKEY RRSet if found. The structure is {domain_name: rrset_data}. Returns None if no DNSKEY records are found or an error occurs. #### Response Example ```json { "example.com.": "DNSKEY RRSet data..." } ``` ``` -------------------------------- ### GET /spf/check Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/spf.html Checks the SPF record for a domain and returns a validation status along with parsed data or error information. ```APIDOC ## GET /spf/check ### Description Returns a dictionary containing the parsed SPF record or an error if the record is invalid or unreachable. ### Parameters #### Query Parameters - **domain** (str) - Required - The domain name to check. - **parked** (bool) - Optional - Indicates if the domain is parked. - **nameservers** (list) - Optional - A list of nameservers to query. - **resolver** (dns.resolver.Resolver) - Optional - A custom resolver object. - **timeout** (float) - Optional - Seconds to wait for DNS response. - **timeout_retries** (int) - Optional - Number of retries after timeout. ### Response #### Success Response (200) - **record** (str) - The SPF record string. - **parsed** (dict) - The parsed SPF record. - **dns_lookups** (int) - Number of DNS lookups. - **void_dns_lookups** (int) - Number of void DNS lookups. - **valid** (bool) - True if valid. - **warnings** (list) - List of warnings. #### Error Response (200) - **valid** (bool) - False. - **error** (str) - The error message. ``` -------------------------------- ### GET /dns/txt_records Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/utils.html Retrieves TXT records for a specified domain. Supports custom nameservers, resolver configurations, and timeout settings. ```APIDOC ## GET /dns/txt_records ### Description Queries DNS for TXT records associated with a given domain. ### Method GET ### Endpoint /dns/txt_records ### Parameters #### Query Parameters - **domain** (str) - Required - The domain name to query. - **nameservers** (list[str | Nameserver]) - Optional - A list of nameservers to query. - **quoted_txt_segments** (bool) - Optional - If true, preserves quotes in TXT records. - **resolver** (dns.resolver.Resolver) - Optional - A custom resolver object. - **timeout** (float) - Optional - Timeout in seconds for DNS queries. Defaults to 2.0. - **timeout_retries** (int) - Optional - Number of retries after a timeout. Defaults to 2. ### Response #### Success Response (200) - **records** (list[str]) - A list of TXT records found for the domain. #### Response Example ```json { "records": [ "v=spf1 include:_spf.google.com ~all", "dmarc=1; p=quarantine; rua=mailto:dmarc@example.com" ] } ``` ### Errors - **DNSExceptionNXDOMAIN**: The domain does not exist. - **DNSException**: No TXT records found or other DNS errors. ``` -------------------------------- ### Download MTA-STS Policy Source: https://domainaware.github.io/checkdmarc/_modules/checkdmarc/mta_sts.html Downloads the MTA-STS policy file from a specified domain's well-known URI. ```APIDOC ## GET /download_mta_sts_policy ### Description Downloads the MTA-STS policy file from the standard location (`/.well-known/mta-sts.txt`) on the specified domain. ### Method GET ### Endpoint /download_mta_sts_policy ### Parameters #### Query Parameters - **domain** (string) - Required - The domain name from which to download the policy. - **http_timeout** (float) - Optional - The timeout in seconds for the HTTP request. ### Response #### Success Response (200) - **policy** (string) - The content of the MTA-STS policy file. - **warnings** (list) - A list of any warning conditions encountered during the download. #### Response Example { "policy": "v=STSv1\nid=\"20230101\"\nmode=enforce\nmx=\"mail.example.com\" ", "warnings": [] } ### Errors - **MTASTSPolicyDownloadError**: If the policy cannot be downloaded (e.g., network error, invalid URL, non-200 status code). ```