
Automatisierte Pipeline, die Schweizer Gemeindedomänen auflöst, Websites nach E-Mail-Adressen durchsucht und E-Mail-Anbieter über MX-, SPF-, DKIM-, DMARC- und SMTP-Prüfungen klassifiziert, um digitale Abhängigkeiten abzubilden.
[!IMPORTANT] MXmap hat einen Nachfolger. Dieses Projekt ist zu einer Team-Forschungsarbeit gewachsen, die alle Gemeinden in Deutschland, Österreich und der Schweiz abdeckt: secassure2026.mxmap-project.org (Quellcode). Die Schweizer Karte unter mxmap.ch bleibt online, aber ihre Daten sind ab April 2026 eingefroren und werden nicht mehr aktualisiert.
Interaktive Karten, die zeigen, wo Schweizer Gemeinden ihre E-Mail hosten und wie stark ihre DNS-Infrastruktur an US-Hyperscaler (Microsoft, Google, AWS) gebunden ist – im Vergleich zu Schweizer Anbietern und Selbsthosting-Lösungen.
Die Daten-Pipeline besteht aus zwei Stufen:
Domains auflösen — Ruft alle ~2100 Schweizer Gemeinden von Wikidata und der BFS-API (Bundesamt für Statistik) ab, wendet manuelle Overrides an, extrahiert E-Mail-Adressen von den Gemeinde-Websites, rät Domains aus den Gemeindenamen und verifiziert Kandidaten mit MX-Lookups. Die Übereinstimmung der Quellen wird bewertet, um die beste Domain auszuwählen. Gibt municipality_domains.json aus.
Anbieter klassifizieren — Für jede aufgelöste Domain werden alle MX-Hosts nachgeschlagen, per Musterabgleich geprüft und anschließend 10 parallele Sonden ausgeführt (SPF, DKIM, DMARC, Autodiscover, CNAME-Kette, SMTP-Banner, Tenant, ASN, TXT-Verifikation, SPF-IP). Die gewichteten Hinweise werden aggregiert und Konfidenzwerte (0–100) berechnet. Gibt data.json (vollständig) und data.min.json (minimiert für das Frontend) aus.
flowchart TD
subgraph resolve ["1 · Resolve domains"]
bfs[/"BFS Statistics API"/] --> merge["Merge ~2100 municipalities"]
wikidata[/"Wikidata SPARQL"/] --> merge
overrides[/"overrides.json"/] --> per_muni
merge --> per_muni["Per municipality"]
per_muni --> scrape["Scrape website for<br/>email addresses"]
per_muni --> guess["Guess domains<br/>from name"]
scrape --> mx_verify["MX lookup to<br/>verify domains"]
guess --> mx_verify
mx_verify --> score["Score source<br/>agreement"]
end
score --> domains[("municipality_domains.json")]
domains --> classify_in
subgraph classify ["2 · Classify providers"]
classify_in["Per unique domain"] --> mx_lookup["MX lookup<br/>(all hosts)"]
mx_lookup --> mx_match["Pattern-match MX<br/>+ detect gateway"]
mx_match --> concurrent["10 concurrent probes<br/>SPF · DKIM · DMARC<br/>Autodiscover · CNAME chain<br/>SMTP · Tenant · ASN<br/>TXT verification · SPF IP"]
concurrent --> aggregate["Aggregate weighted<br/>evidence"]
aggregate --> vote["Primary vote<br/>+ confidence scoring"]
end
vote --> data[("data.json + data.min.json")]
data --> frontend["Leaflet map<br/>mxmap.ch"]
Siehe classifier.py für die vollständigen Implementierungsdetails, aber zusammengefasst
verwenden wir ein gewichtetes Evidenzsystem, bei dem jede Sonde Signale unterschiedlicher Stärke zu verschiedenen Anbieterklassifikationen beiträgt.
uv sync
# Stage 1: resolve municipality domains
uv run resolve-domains
# Stage 2: classify email providers
uv run classify-providers
# Serve the map locally
python -m http.server
uv sync --group dev
# Run tests (90% coverage threshold enforced)
uv run pytest --cov --cov-report=term-missing
# Lint & format
uv run ruff check src tests
uv run ruff format src tests
Länderspezifische Forks, alphabetisch nach Ländercode:
Neue Länder-Forks sind willkommen – erwäge, mit der Pipeline des Nachfolgers zu starten, die eine DANE/DNSSEC/SPF/DMARC-Scan-Phase hinzufügt.
Verwandte Projekte:
Siehe auch die Forks dieses Repositorys.
Wenn du eine Fehlklassifizierung entdeckst, öffne bitte ein Issue mit der BFS-Nummer und dem korrekten Anbieter.
Für Gemeinden, bei denen die automatische Erkennung fehlschlägt, können Korrekturen in overrides.json ergänzt werden.