
Pipeline automatisé qui résout les domaines des communes suisses, extrait les adresses e-mail des sites web et classe les fournisseurs de messagerie via des sondes MX, SPF, DKIM, DMARC et SMTP afin de cartographier les dépendances numériques.
[!IMPORTANT] MXmap a un successeur. Ce projet a évolué en un effort de recherche d'équipe couvrant toutes les communes d'Allemagne, d'Autriche et de Suisse : secassure2026.mxmap-project.org (source). La carte suisse sur mxmap.ch reste en ligne, mais ses données sont figées depuis avril 2026 et ne seront plus mises à jour.
Cartes interactives montrant où les communes suisses hébergent leur messagerie et à quel point leur DNS est lié aux hyperscalers américains (Microsoft, Google, AWS) par rapport aux fournisseurs suisses et aux solutions auto-hébergées.
Le pipeline de données comporte deux étapes :
Résoudre les domaines — Récupère les ~2100 communes suisses depuis Wikidata et l'API BFS (Office fédéral de la statistique), applique des corrections manuelles, extrait les adresses e-mail des sites web communaux, devine les domaines à partir des noms de communes et vérifie les candidats avec des requêtes MX. Évalue l'accord entre les sources pour choisir le meilleur domaine. Génère municipality_domains.json.
Classifier les fournisseurs — Pour chaque domaine résolu, recherche tous les hôtes MX, les compare à des motifs, puis lance 10 sondes concurrentes (SPF, DKIM, DMARC, Autodiscover, chaîne CNAME, bannière SMTP, Tenant, ASN, vérification TXT, IP SPF). Agrège les preuves pondérées, calcule les scores de confiance (0–100). Génère data.json (complet) et data.min.json (minifié pour le frontal).
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"]
voir classifier.py pour le détail complet de l'implémentation, mais en résumé,
nous utilisons un système de preuves pondérées où chaque sonde apporte des signaux de force variable vers différentes classifications de fournisseurs.
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
Forks spécifiques à chaque pays, classés par ordre alphabétique de code pays :
Les nouveaux forks par pays sont les bienvenus — pensez à partir du pipeline du successeur, qui ajoute une étape de scan DANE/DNSSEC/SPF/DMARC.
Projets associés :
Voir aussi les forks de ce dépôt.
Si vous repérez une mauvaise classification, veuillez ouvrir une issue avec le numéro BFS et le bon fournisseur.
Pour les communes où la détection automatique échoue, des corrections peuvent être ajoutées dans overrides.json.