modul-x / app /validator /i18n.py
FortyDN Dev
v3.0.0: fully autonomous engine — remove MillionVerifier, add DoH DNS worker, AI risk scorer (HF PRO, circuit breaker), i18n, normalized verdicts, remote SMTP worker
de745bf
Raw History Blame Contribute Delete
2.73 kB
"""Internationalization primitives for the autonomous engine.
Covers the two i18n hard requirements from the architecture spec:
7.1 Punycode / IDN domains — a Unicode domain (e.g. bücher.example) must be
normalized to Punycode (RFC 3492, "xn--…") before MX resolution and SMTP
probing. The `email-validator` library already does this at Layer 1, but
every other layer (DoH resolver, DNS cache keys, SMTP dialogue) must ALSO
receive the ASCII form, so the conversion lives here as the single source.
7.2 EAI / SMTPUTF8 local parts — a non-ASCII local part (utf8@bücher.example)
can only be delivered when the receiving MX advertises SMTPUTF8. Without
an SMTP dialogue we cannot observe the advertisement, so the engine must
NOT claim a definitive verdict for these addresses: it refuses the probe
deterministically and reports `unsupported_eai` (honest unknown, never a
fake invalid).
"""
from __future__ import annotations
import idna
EAI_REASON = "unsupported_eai"
def to_punycode(domain: str) -> str:
"""Return the ASCII (Punycode) form of a domain, best-effort.
Already-ASCII domains pass through unchanged (fast path). A domain that
cannot be encoded (malformed Unicode, over-long label) is returned as-is —
DNS will then fail naturally and the verdict degrades honestly.
"""
if not domain:
return domain
try:
domain.encode("ascii")
return domain # pure ASCII — nothing to do
except UnicodeEncodeError:
pass
try:
return idna.encode(domain, uts46=True).decode("ascii")
except Exception:
# Last resort: Python's builtin IDNA (RFC 3490 without uts46 mapping)
try:
return domain.encode("idna").decode("ascii")
except Exception:
return domain
def domain_is_unicode(domain: str) -> bool:
"""True when the domain needs Punycode (contains non-ASCII labels)."""
try:
domain.encode("ascii")
return False
except UnicodeEncodeError:
return True
def local_part_is_ascii(local_part: str) -> bool:
"""True when the local part is plain ASCII (no EAI/SMTPUTF8 needed)."""
try:
(local_part or "").encode("ascii")
return True
except UnicodeEncodeError:
return False
def eai_gate(local_part: str) -> str | None:
"""Deterministic EAI gate for the mailbox-probe layers.
Returns None when the local part is ASCII and probing may proceed.
Returns the machine reason ("unsupported_eai") when the address requires
SMTPUTF8 and this deployment cannot honestly verify it.
"""
if local_part_is_ascii(local_part):
return None
return EAI_REASON