Merge pull request #76 from christianlouis/copilot/update-dkim-selectors

Fix DKIM selector extraction: surface all working selectors and auto-discovered report selectors
This commit is contained in:
Christian Krakau-Louis
2026-03-30 01:57:12 +02:00
committed by GitHub
5 changed files with 121 additions and 32 deletions
+40 -2
View File
@@ -49,7 +49,7 @@ MOCK_DNS_RESULT = DomainDNSResult(
spf=True,
spf_record="v=spf1 include:_spf.google.com ~all",
dkim=True,
dkim_selector="google",
dkim_selectors=["google"],
dkim_record="v=DKIM1; k=rsa; p=ABC",
)
@@ -79,7 +79,9 @@ def test_get_selectors_empty(client: TestClient):
"""Returns an empty list when no selectors have been configured."""
response = client.get(f"/api/v1/domains/{DOMAIN}/selectors")
assert response.status_code == 200
assert response.json() == {"selectors": []}
data = response.json()
assert data["selectors"] == []
assert "report_selectors" in data
def test_get_selectors_unknown_domain(client: TestClient):
@@ -176,6 +178,42 @@ def test_delete_selector_unknown_domain(client: TestClient):
# ---------------------------------------------------------------------------
def test_get_selectors_includes_report_selectors(client: TestClient):
"""Report selectors (from DMARC report records) are returned in report_selectors."""
response = client.get(f"/api/v1/domains/{DOMAIN}/selectors")
assert response.status_code == 200
data = response.json()
# The MINIMAL_REPORT has a record with selector "google" in its dkim auth results
assert "google" in data["report_selectors"]
def test_get_selectors_report_selector_moves_to_manual_when_added(client: TestClient):
"""A selector discovered from reports should appear only in 'selectors' once added manually."""
# Confirm it's in report_selectors before adding
r1 = client.get(f"/api/v1/domains/{DOMAIN}/selectors")
assert "google" in r1.json()["report_selectors"]
# Add it as a manual selector
client.post(f"/api/v1/domains/{DOMAIN}/selectors", json={"selector": "google"})
r2 = client.get(f"/api/v1/domains/{DOMAIN}/selectors")
data = r2.json()
assert "google" in data["selectors"]
# It must not appear in both lists
assert "google" not in data["report_selectors"]
def test_dns_endpoint_returns_dkim_selectors_as_list(client: TestClient):
"""The /dns endpoint should return dkimSelectors as a list."""
with _mock_dns():
response = client.get(f"/api/v1/domains/{DOMAIN}/dns")
assert response.status_code == 200
data = response.json()
assert isinstance(data["dkimSelectors"], list)
assert "google" in data["dkimSelectors"]
def test_dns_endpoint_returns_real_data(client: TestClient):
"""The /dns endpoint should return the mocked DNS check result."""
with _mock_dns():
+26 -9
View File
@@ -110,9 +110,9 @@ async def test_check_dkim_found_first_selector():
provider = FakeDNSProvider(
{"google._domainkey.example.com": ["v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3"]}
)
found, selector, record = await provider.check_dkim("example.com", ["google", "mail"])
found, selectors, record = await provider.check_dkim("example.com", ["google", "mail"])
assert found is True
assert selector == "google"
assert selectors == ["google"]
assert record is not None
@@ -121,17 +121,34 @@ async def test_check_dkim_found_second_selector():
provider = FakeDNSProvider(
{"mail._domainkey.example.com": ["v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3"]}
)
found, selector, record = await provider.check_dkim("example.com", ["google", "mail"])
found, selectors, record = await provider.check_dkim("example.com", ["google", "mail"])
assert found is True
assert selector == "mail"
assert selectors == ["mail"]
@pytest.mark.asyncio
async def test_check_dkim_found_multiple_selectors():
"""When multiple selectors resolve, all are returned."""
provider = FakeDNSProvider(
{
"google._domainkey.example.com": ["v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3"],
"mail._domainkey.example.com": ["v=DKIM1; k=rsa; p=XYZ"],
}
)
found, selectors, record = await provider.check_dkim("example.com", ["google", "mail"])
assert found is True
assert "google" in selectors
assert "mail" in selectors
assert len(selectors) == 2
assert record is not None # record of the first match
@pytest.mark.asyncio
async def test_check_dkim_not_found():
provider = FakeDNSProvider({})
found, selector, record = await provider.check_dkim("example.com", ["google", "mail"])
found, selectors, record = await provider.check_dkim("example.com", ["google", "mail"])
assert found is False
assert selector is None
assert selectors == []
assert record is None
@@ -149,7 +166,7 @@ async def test_check_domain_all_present():
assert result.dmarc is True
assert result.spf is True
assert result.dkim is True
assert result.dkim_selector == "google"
assert result.dkim_selectors == ["google"]
@pytest.mark.asyncio
@@ -168,7 +185,7 @@ async def test_check_domain_uses_common_selectors_as_fallback():
provider = FakeDNSProvider({"default._domainkey.example.com": ["v=DKIM1; k=rsa; p=ABC"]})
result = await provider.check_domain("example.com", selectors=[])
assert result.dkim is True
assert result.dkim_selector == "default"
assert result.dkim_selectors == ["default"]
@pytest.mark.asyncio
@@ -178,7 +195,7 @@ async def test_check_domain_manual_selectors_take_priority():
provider = FakeDNSProvider({"custom._domainkey.example.com": ["v=DKIM1; k=rsa; p=XYZ"]})
result = await provider.check_domain("example.com", selectors=["custom"])
assert result.dkim is True
assert result.dkim_selector == "custom"
assert result.dkim_selectors == ["custom"]
# ---------------------------------------------------------------------------