nadzoring.dns_lookup.validation module

DNS record validation functions.

This module is split into small, single-responsibility validators:

Each validator returns a plain dict or primitive; none raise exceptions.

Typical usage via nadzoring.dns_lookup.health:

from nadzoring.dns_lookup.validation import (
    validate_mx_records,
    validate_txt_records,
    determine_status,
)

mx_result = validate_mx_records(["10 mail.example.com", "20 backup.example.com"])
print(mx_result["valid"])  # True
print(mx_result["issues"])  # []

status = determine_status(85)  # "healthy"
nadzoring.dns_lookup.validation._apply_type_specific_checks(rtype: str, record_result: dict[str, Any], score: int, accumulator: dict[str, list[str]]) int[source]

Apply record-type-specific scoring rules.

Parameters:
  • rtype – DNS record type.

  • record_result – Dict with record data.

  • score – Current score before type-specific adjustments.

  • accumulator – Issues/warnings accumulator updated in-place.

Returns:

Adjusted score.

nadzoring.dns_lookup.validation._parse_mx_priority(mx: str) int | None[source]

Parse the numeric priority from an MX record string.

Parameters:

mx – MX record string in "priority mailserver" format.

Returns:

Integer priority, or None when the format is invalid.

nadzoring.dns_lookup.validation._score_mx(records: list[str], score: int, accumulator: dict[str, list[str]]) int[source]

Deduct points for duplicate MX priorities or malformed records.

nadzoring.dns_lookup.validation._score_txt(records: list[str], score: int, accumulator: dict[str, list[str]]) int[source]

Deduct points for SPF / DKIM issues in TXT records.

nadzoring.dns_lookup.validation._validate_dkim(txt: str) tuple[list[str], list[str]][source]

Check a single DKIM record; return (issues, warnings).

nadzoring.dns_lookup.validation._validate_spf(txt: str) tuple[list[str], list[str]][source]

Check a single SPF record; return (issues, warnings).

nadzoring.dns_lookup.validation.calculate_record_score(rtype: str, record_result: dict[str, Any], accumulator: dict[str, list[str]]) int[source]

Calculate a health score for a single DNS record type.

Starts at 100 and deducts points for errors, missing records, or type-specific issues. Side-effects: appends messages to accumulator["issues"] and accumulator["warnings"].

Parameters:
  • rtype – DNS record type (e.g. "A", "MX", "TXT").

  • record_result – Dict with optional "error" and "records" keys (a DNSResult).

  • accumulator – Dict with "issues" and "warnings" lists that are updated in-place.

Returns:

Score between 0 and 100.

nadzoring.dns_lookup.validation.determine_status(score: int) str[source]

Map a numeric health score to a status label.

Thresholds:

  • score >= 80"healthy"

  • score >= 50"degraded"

  • score < 50"unhealthy"

Parameters:

score – Numeric score in the range 0-100.

Returns:

Status label string.

Examples

>>> determine_status(85)
'healthy'
>>> determine_status(65)
'degraded'
>>> determine_status(30)
'unhealthy'
nadzoring.dns_lookup.validation.validate_mx_records(mx_records: list[str]) dict[str, bool | list[str]][source]

Validate MX records for duplicate priority values.

Parameters:

mx_records – MX record strings in "priority mailserver" format.

Returns:

Dict with "valid" (bool), "issues" (list[str]), and "warnings" (list[str]) keys.

Examples

Valid records:

result = validate_mx_records(
    ["10 mail.example.com", "20 backup.example.com"]
)
assert result["valid"] is True
assert result["issues"] == []

Duplicate priorities:

result = validate_mx_records(
    ["10 mail1.example.com", "10 mail2.example.com"]
)
assert result["valid"] is False
assert "Duplicate priority: 10" in result["issues"]
nadzoring.dns_lookup.validation.validate_txt_records(txt_records: list[str]) dict[str, bool | list[str]][source]

Validate TXT records for SPF and DKIM compliance.

Checks:

  • SPF — warns when ~all or -all mechanism is absent

  • DKIM — marks invalid when the p= public-key tag is missing

Parameters:

txt_records – List of TXT record strings.

Returns:

Dict with "valid" (bool), "issues" (list[str]), and "warnings" (list[str]) keys.

Examples

SPF without terminator:

result = validate_txt_records(["v=spf1 include:spf.example.com"])
assert result["valid"] is True  # SPF warning only
assert result["warnings"] != []

Missing DKIM key:

result = validate_txt_records(["v=DKIM1; k=rsa;"])
assert result["valid"] is False
assert result["issues"] != []

All good:

result = validate_txt_records(
    [
        "v=spf1 include:spf.example.com ~all",
        "v=DKIM1; k=rsa; p=MIIBIjANBg...",
    ]
)
assert result["valid"] is True
assert result["issues"] == []