115 lines
3.9 KiB
Python
115 lines
3.9 KiB
Python
"""Tests for company shared-MX DNS onboarding."""
|
|
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from app.services.dns_verification import (
|
|
ownership_record_value,
|
|
verify_company_dns,
|
|
verify_dmarc,
|
|
)
|
|
from app.services.domain_policy import assert_company_domain_allowed
|
|
from app.services.domain_provisioning import (
|
|
account_is_domain_owner,
|
|
build_company_dns_records,
|
|
build_shared_mx_spf_value,
|
|
register_relay_domain,
|
|
)
|
|
|
|
|
|
def test_build_company_dns_records_use_shared_mx_and_spf_include():
|
|
records = build_company_dns_records(
|
|
"acme.com",
|
|
"mail.gentic.email",
|
|
"agmail",
|
|
"abc123public",
|
|
"_spf.gentic.email",
|
|
"verify-token-123",
|
|
)
|
|
purposes = [record["purpose"] for record in records]
|
|
assert purposes == ["ownership", "mx", "spf", "dkim", "dmarc"]
|
|
|
|
ownership = next(record for record in records if record["purpose"] == "ownership")
|
|
mx = next(record for record in records if record["purpose"] == "mx")
|
|
spf = next(record for record in records if record["purpose"] == "spf")
|
|
dkim = next(record for record in records if record["purpose"] == "dkim")
|
|
|
|
assert ownership["host"] == "_agmail-verify"
|
|
assert ownership["value"] == ownership_record_value("verify-token-123")
|
|
assert mx["host"] == "@"
|
|
assert mx["value"] == "mail.gentic.email"
|
|
assert mx["priority"] == 10
|
|
assert spf["value"] == "v=spf1 include:_spf.gentic.email ~all"
|
|
assert dkim["host"] == "agmail._domainkey"
|
|
assert "abc123public" in dkim["value"]
|
|
assert not any(record.get("purpose") == "mail_host" for record in records)
|
|
|
|
|
|
def test_build_shared_mx_spf_value():
|
|
assert build_shared_mx_spf_value("_spf.gentic.email") == (
|
|
"v=spf1 include:_spf.gentic.email ~all"
|
|
)
|
|
|
|
|
|
def test_register_relay_domain_appends_once(tmp_path, monkeypatch):
|
|
relay_file = tmp_path / "domains.list"
|
|
monkeypatch.setenv("RELAY_DOMAINS_FILE", str(relay_file))
|
|
|
|
from app.config import get_settings
|
|
|
|
get_settings.cache_clear()
|
|
|
|
register_relay_domain("Acme.COM")
|
|
register_relay_domain("acme.com")
|
|
|
|
assert relay_file.read_text(encoding="utf-8") == "acme.com\n"
|
|
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def test_assert_company_domain_allowed_blocks_platform_and_google():
|
|
with pytest.raises(ValueError, match="platform domain"):
|
|
assert_company_domain_allowed("gentic.email", "gentic.email")
|
|
with pytest.raises(ValueError, match="cannot be used"):
|
|
assert_company_domain_allowed("google.com", "gentic.email")
|
|
assert assert_company_domain_allowed("acme.com", "gentic.email") == "acme.com"
|
|
|
|
|
|
@patch("app.services.dns_verification._lookup_txt")
|
|
def test_verify_dmarc_requires_exact_match(mock_txt):
|
|
expected = "v=DMARC1; p=quarantine; rua=mailto:dmarc@acme.com"
|
|
mock_txt.return_value = ["v=DMARC1; p=reject; rua=mailto:security@google.com"]
|
|
verified, message = verify_dmarc("acme.com", expected)
|
|
assert verified is False
|
|
assert "exactly" in message.lower()
|
|
|
|
|
|
@patch("app.services.dns_verification._lookup_txt")
|
|
@patch("app.services.dns_verification._lookup_mx")
|
|
def test_verify_company_dns_all_pass(mock_mx, mock_txt):
|
|
mock_mx.return_value = [(10, "mail.gentic.email")]
|
|
mock_txt.side_effect = lambda name: {
|
|
"_agmail-verify.acme.com": [ownership_record_value("token-abc")],
|
|
"acme.com": ['v=spf1 include:_spf.gentic.email ~all'],
|
|
"agmail._domainkey.acme.com": ["v=DKIM1; k=rsa; p=abc123"],
|
|
"_dmarc.acme.com": ["v=DMARC1; p=quarantine; rua=mailto:dmarc@acme.com"],
|
|
}.get(name, [])
|
|
|
|
checks = verify_company_dns(
|
|
domain_name="acme.com",
|
|
shared_mail_host="mail.gentic.email",
|
|
dkim_selector="agmail",
|
|
dkim_public_key="abc123",
|
|
platform_spf_include="_spf.gentic.email",
|
|
verification_token="token-abc",
|
|
)
|
|
|
|
assert all(check["verified"] for check in checks)
|
|
assert [check["purpose"] for check in checks] == [
|
|
"ownership",
|
|
"mx",
|
|
"spf",
|
|
"dkim",
|
|
"dmarc",
|
|
]
|