Bonnes pratiques¶
Haute disponibilité¶
Enregistrements MX multiples¶
La première ligne de defense contre les pannes est la redundance DNS avec plusieurs enregistrements MX :
company.io. 300 IN MX 10 mail-1.company.io.
company.io. 300 IN MX 10 mail-2.company.io.
company.io. 300 IN MX 20 mail-backup.company.io.
| Configuration | Comportement |
|---|---|
| MX priorité 10 x2 | Load balancing entre mail-1 et mail-2 (même priorité) |
| MX priorité 20 | Backup — utilise uniquement si les deux MX 10 sont down |
Priorité identique = load balancing
Quand deux enregistrements MX ont la même priorité, les serveurs expéditeurs repartissent la charge aleatoirement entre les deux. C'est le mécanisme de HA le plus simple pour la messagerie.
Clustering Stalwart¶
Stalwart supporte le clustering actif-actif avec un backend de stockage partage :
graph TD
S1["Stalwart 1<br/>10.20.1.30"] --> PG["PostgreSQL<br/>(stockage partage)"]
S2["Stalwart 2<br/>10.20.1.31"] --> PG
PG --> MinIO["MinIO (S3)<br/>(blobs)"] Configuration du clustering :
# Instance 1
[cluster]
node-id = 1
bind-addr = "10.20.1.30:1179"
seed-nodes = ["10.20.1.31:1179"]
# Instance 2
[cluster]
node-id = 2
bind-addr = "10.20.1.31:1179"
seed-nodes = ["10.20.1.30:1179"]
DNS failover¶
Le DNS est le mécanisme de failover natif du protocole email. Configurer des TTL courts pour un basculement rapide :
| Enregistrement | TTL recommande | Justification |
|---|---|---|
| MX | 300 s (5 min) | Basculement rapide entre serveurs |
| A (mail) | 300 s | Mise à jour rapide en cas de migration |
| SPF, DKIM | 3600 s (1 h) | Changent rarement |
| DMARC | 3600 s | Changent rarement |
Stratégie de sauvegarde¶
Sauvegarde des boites aux lettres¶
| Méthode | Outil | Fréquence | RPO |
|---|---|---|---|
| Export Stalwart | API /api/store/export | Quotidien | 24 h |
| Snapshot PostgreSQL | pg_dump / pg_basebackup | Quotidien | 24 h |
| Snapshot S3 | Réplication MinIO | Continu | ~0 (sync) |
| IMAP sync | imapsync, offlineimap | Quotidien | 24 h |
Script de sauvegarde¶
#!/bin/bash
# backup-stalwart.sh — Sauvegarde quotidienne
BACKUP_DIR="/backup/stalwart"
DATE=$(date +%Y%m%d)
RETENTION_DAYS=30
# 1. Export des donnees Stalwart
curl -s -X GET "http://localhost:8080/api/store/export" \
-H "Authorization: Bearer ${STALWART_ADMIN_TOKEN}" \
-o "${BACKUP_DIR}/stalwart-${DATE}.tar"
# 2. Chiffrer la sauvegarde
age -r "${BACKUP_PUBLIC_KEY}" \
-o "${BACKUP_DIR}/stalwart-${DATE}.tar.age" \
"${BACKUP_DIR}/stalwart-${DATE}.tar"
rm "${BACKUP_DIR}/stalwart-${DATE}.tar"
# 3. Supprimer les anciennes sauvegardes
find "${BACKUP_DIR}" -name "*.age" -mtime +${RETENTION_DAYS} -delete
# 4. Verifier la taille (alerte si trop petite = sauvegarde incomplete)
SIZE=$(stat -f%z "${BACKUP_DIR}/stalwart-${DATE}.tar.age" 2>/dev/null \
|| stat --format=%s "${BACKUP_DIR}/stalwart-${DATE}.tar.age")
if [ "$SIZE" -lt 1048576 ]; then
echo "ALERTE: Sauvegarde anormalement petite (${SIZE} octets)" >&2
exit 1
fi
echo "Sauvegarde terminee: stalwart-${DATE}.tar.age (${SIZE} octets)"
Test de restauration¶
# Restaurer sur une instance de test (jamais en production directement)
podman run -d --name stalwart-restore \
-v /tmp/restore-data:/opt/stalwart-mail/data:Z \
-p 18080:8080 \
docker.io/stalwartlabs/stalwart-mail:latest
# Importer la sauvegarde
age -d -i /path/to/private-key \
-o /tmp/stalwart-restore.tar \
/backup/stalwart/stalwart-20260416.tar.age
curl -X POST "http://localhost:18080/api/store/import" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-F "file=@/tmp/stalwart-restore.tar"
# Verifier que les boites sont accessibles
curl -s http://localhost:18080/api/principal | jq '.items | length'
Tester la restauration mensuellement
Une sauvegarde qui n'a jamais ete testée n'est pas une sauvegarde. Planifier un test de restauration mensuel sur une instance isolee.
Deliverabilite¶
Reputation IP¶
La deliverabilite depend en grande partie de la reputation de l'adresse IP du serveur mail :
| Facteur | Impact | Action |
|---|---|---|
| IP neuve | Aucune reputation → mefiante | Warm-up progressif |
| IP blacklistee | Emails rejetes | Delister, identifier la cause |
| Reverse DNS absent | Emails rejetes par beaucoup | Configurer le PTR record |
| Volume irregulier | Pics suspects | Lisser le volume d'envoi |
| Taux de rebond | > 5% = penalise | Nettoyer les listes, vérifier adresses |
Warm-up d'une IP neuve¶
Quand vous déployer un nouveau serveur mail sur une IP sans historique, les grands fournisseurs (Gmail, Microsoft) limitent le volume accepte :
| Semaine | Volume quotidien max | Actions |
|---|---|---|
| 1 | 50 emails | Envoyer a des destinataires engages |
| 2 | 200 emails | Augmenter progressivement |
| 3 | 500 emails | Monitorer le taux de delivery |
| 4 | 1 000 emails | Vérifier les postmaster tools |
| 5-8 | +1 000/semaine | Montee progressive |
| 8+ | Volume normal | Reputation etablie |
Feedback loops¶
S'enregistrer aux programmes de feedback des grands fournisseurs pour recevoir les signalements de spam :
| Fournisseur | Programme | URL d'inscription |
|---|---|---|
| Gmail Postmaster Tools | https://postmaster.google.com/ | |
| Microsoft | SNDS + JMRP | https://sendersupport.olc.protection.outlook.com/ |
| Yahoo | Complaint Feedback Loop | https://senders.yahooinc.com/ |
Monitoring des blacklists¶
# Verifier si l'IP est blacklistee
# Utiliser MX Toolbox ou un script de verification
for rbl in \
zen.spamhaus.org \
bl.spamcop.net \
b.barracudacentral.org \
dnsbl.sorbs.net; do
result=$(dig +short "10.113.0.203.${rbl}" 2>/dev/null)
if [ -n "$result" ]; then
echo "BLACKLISTE sur ${rbl}: ${result}"
else
echo "OK: ${rbl}"
fi
done
Reglage anti-spam¶
Faux positifs¶
Les faux positifs (emails legitimes marques comme spam) sont le problème operationnel numero un de la messagerie :
| Cause fréquente | Solution |
|---|---|
| Score trop agressif | Augmenter le seuil de spam (5.0 → 6.0) |
| DNSBL trop large | Retirer les RBL agressives |
| Domaine partenaire penalise | Ajouter en allowlist |
| Signature DKIM cassee (forwarding) | Vérifier la chaîne ARC |
| Contenu marketing legitime | Entraîner le filtre bayesien (ham) |
Entrainement du filtre bayesien¶
# Apprendre un email comme ham (non-spam)
curl -X POST "http://localhost:8080/api/spam/train" \
-H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"class": "ham", "message": "<raw-email-base64>"}'
# Apprendre un email comme spam
curl -X POST "http://localhost:8080/api/spam/train" \
-H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"class": "spam", "message": "<raw-email-base64>"}'
Allowlists et blocklists operationnelles¶
# Domaines de confiance (jamais filtres)
[spam.list.allowlist]
domains = [
"partenaire-officiel.fr",
"service-public.gouv.fr",
"banque-entreprise.fr"
]
# Adresses specifiques en allowlist
addresses = [
"important-contact@external.com"
]
Migration depuis Exchange/Gmail ou Postfix¶
Outils de migration IMAP¶
| Outil | Langage | Fonctionnalité | Recommandation |
|---|---|---|---|
| imapsync | Perl | Sync IMAP → IMAP, incremental, fiable | Référence pour la migration |
| offlineimap | Python | Sync IMAP ↔ Maildir | Alternative open source |
| larch | Ruby | Sync IMAP → IMAP, simple | Petites migrations |
Processus de migration¶
# 1. Migration incrementale (pendant la coexistence)
imapsync \
--host1 old-server.company.io --user1 alice --password1 "old-pwd" \
--host2 mail.company.io --user2 alice@company.io --password2 "new-pwd" \
--ssl1 --ssl2 \
--syncinternaldates \
--exclude "Spam|Trash"
# 2. Migration finale (apres basculement DNS)
imapsync \
--host1 old-server.company.io --user1 alice --password1 "old-pwd" \
--host2 mail.company.io --user2 alice@company.io --password2 "new-pwd" \
--ssl1 --ssl2 \
--syncinternaldates \
--delete2duplicates
Plan de migration type¶
| Étape | Action | Duree |
|---|---|---|
| 1 | Déployer Stalwart, configurer DNS (sans changer MX) | 1 semaine |
| 2 | Tester avec un groupe pilote (10 utilisateurs) | 2 semaines |
| 3 | Migration incrementale des boites (imapsync) | 1 semaine |
| 4 | Basculer le MX vers Stalwart | 1 jour |
| 5 | Migration finale (derniers emails) | 1 jour |
| 6 | Decommissionner l'ancien serveur (apres 30 jours) | — |
Coexistence avec l'ancien serveur
Pendant la migration, les deux serveurs coexistent. L'ancien serveur reste le MX primaire jusqu'a l'étape 4. Les utilisateurs migres accedent a Stalwart, les autres restent sur l'ancien. Cela minimise le risque.
Troubleshooting¶
Echecs de livraison¶
| Symptome | Cause probable | Diagnostic |
|---|---|---|
550 5.1.1 User unknown | Destinataire inexistant | Vérifier l'adresse |
550 5.7.1 Rejected by SPF | IP non autorisee dans SPF | dig company.io TXT \| grep spf |
421 Too many connections | Rate limiting du destinataire | Reduire le débit sortant |
451 Temporary failure | Erreur transitoire (DNS, stockage) | Vérifier DNS et stockage, reessayer |
554 5.7.1 Rejected by DMARC | Alignement DKIM/SPF échoue | Vérifier la config DKIM et le From: |
| Email en spam chez Gmail | Reputation IP / SPF/DKIM incomplet | Gmail Postmaster Tools |
Problèmes TLS¶
# Tester la connexion TLS SMTP
openssl s_client -connect mail.company.io:465 -quiet
# Tester STARTTLS SMTP
openssl s_client -connect mail.company.io:25 -starttls smtp -quiet
# Tester IMAPS
openssl s_client -connect mail.company.io:993 -quiet
# Verifier le certificat
echo | openssl s_client -connect mail.company.io:465 2>/dev/null \
| openssl x509 -noout -dates -subject -issuer
Alignement DKIM¶
# Verifier que DKIM signe correctement
# Envoyer un email de test et examiner les en-tetes
swaks --to test@gmail.com \
--from alice@company.io \
--server mail.company.io:587 \
--auth LOGIN --tls
# Dans les en-tetes du mail recu, verifier :
# Authentication-Results: ...
# dkim=pass header.d=company.io header.s=default
# spf=pass
# dmarc=pass
Queue bloquee¶
# Lister les emails en queue
curl -s http://localhost:8080/api/queue/list \
-H "Authorization: Bearer <admin-token>" | jq '.items | length'
# Voir les details d'un message en queue
curl -s http://localhost:8080/api/queue/list \
-H "Authorization: Bearer <admin-token>" | jq '.items[0]'
# Forcer la relivraison
curl -X POST http://localhost:8080/api/queue/retry \
-H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"ids": ["<message-id>"]}'
# Purger les messages bloques depuis plus de 7 jours
curl -X DELETE "http://localhost:8080/api/queue/purge?older-than=7d" \
-H "Authorization: Bearer <admin-token>"
Autoconfig qui ne fonctionne pas¶
| Symptome | Cause probable | Solution |
|---|---|---|
| Thunderbird ne détecte pas le serveur | DNS CNAME autoconfig manquant | Ajouter l'enregistrement DNS |
| Outlook ne détecte pas le serveur | SRV _autodiscover._tcp manquant | Ajouter l'enregistrement DNS |
| Autoconfig retourne une erreur 404 | Reverse proxy ne route pas vers Stalwart | Vérifier la config du reverse proxy |
| Certificat invalide | CNAME pointe vers un autre domaine | Vérifier que le certificat couvre le CNAME |
Commandes de diagnostic¶
# Test complet de la configuration email d'un domaine
# MX, SPF, DKIM, DMARC, reverse DNS, TLS, blacklists
dig company.io MX +short
dig company.io TXT +short
dig default._domainkey.company.io TXT +short
dig _dmarc.company.io TXT +short
dig -x $(dig mail.company.io A +short) +short
# Tester l'envoi SMTP avec details verbeux
swaks --to test@example.com \
--from alice@company.io \
--server mail.company.io:587 \
--auth LOGIN --tls \
--auth-user alice@company.io \
-tlsc -tls-verify \
--header "Subject: Test diagnostique"
# Verifier les logs Stalwart pour les erreurs recentes
podman logs --since 1h stalwart-mail 2>&1 | grep -iE "error|warn|fail"
Checklist operationnelle¶
| Fréquence | Action | Outil |
|---|---|---|
| Quotidien | Vérifier la taille de la queue | Grafana dashboard |
| Quotidien | Vérifier les echecs de livraison | Alertes Prometheus |
| Hebdo | Analyser les rapports DMARC | DMARC Analyzer |
| Hebdo | Vérifier les blacklists IP | MX Toolbox / script |
| Mensuel | Tester la restauration de sauvegarde | Script de restauration |
| Mensuel | Revoir les regles anti-spam (faux positifs) | Retours utilisateurs |
| Trimestriel | Rotation des cles DKIM | API Stalwart + DNS |
| Trimestriel | Mise à jour de Stalwart | Podman pull + restart |
| Annuel | Revoir la politique de retention | DPO + juridique |
| Annuel | Audit de sécurité de la configuration | Checklist + pentest |
Synthese¶
Opérer une messagerie auto-hebergee demande de la rigueur sur trois axes : la deliverabilite (reputation IP, SPF/DKIM/DMARC, monitoring des blacklists), la fiabilité (HA via MX multiples et clustering, sauvegardes testées) et la sécurité (TLS, anti-spam, audit). Le warm-up de l'IP et le déploiement progressif de DMARC sont les deux étapes les plus critiques lors d'un nouveau déploiement. La migration depuis un système existant se fait de manière incrementale avec imapsync et un basculement DNS maîtrise.