Héberger son courrier a mauvaise réputation, à raison : un serveur mal configuré voit ses messages finir en indésirables ou refusés, et un serveur mal protégé devient un relais pour les spammeurs. Pourtant, avec un logiciel moderne et une check-list rigoureuse, c’est tout à fait faisable pour un domaine personnel ou une petite structure. Ce tutoriel utilise mox, un serveur de courrier complet écrit en Go et livré en un seul binaire : SMTP entrant et sortant, IMAP, webmail, SPF, DKIM, DMARC, MTA-STS, TLS-RPT, filtrage du courrier indésirable par réputation, et ses propres certificats Let’s Encrypt.

Exemple utilisé : le domaine example.org, le serveur mail.example.org en 203.0.113.25. Comptez une demi-journée, dont une bonne partie à attendre la propagation du DNS.

Schéma des quatre étapes d'un serveur mail mox : identité réseau, SPF DKIM DMARC, MTA-STS, ports, puis vérifications
Ce qui doit être juste avant d’envoyer le premier message.

Pourquoi mox plutôt que Postfix et Dovecot

La pile classique (Postfix, Dovecot, un filtre comme Rspamd, OpenDKIM, un webmail, certbot) fonctionne très bien, mais demande d’assembler et de maintenir six logiciels qui doivent s’entendre. mox fait tout cela d’un bloc, avec des valeurs par défaut sûres et des outils de vérification intégrés. Le revers : un projet plus jeune, dont la configuration change parfois d’une version à l’autre. Lisez les notes de version avant chaque mise à jour.

Prérequis : ce qui ne se rattrape pas

  • une adresse IP fixe et propre : vérifiez qu’elle ne figure pas sur une liste de blocage (Spamhaus, Barracuda…) avant de commencer ; une adresse héritée d’un ancien spammeur est un boulet ;
  • le port 25 sortant ouvert : beaucoup d’hébergeurs le bloquent par défaut sur les VPS. Testez-le avant tout : nc -vz gmail-smtp-in.l.google.com 25. S’il est fermé, il faut le demander au support ;
  • le DNS inverse (PTR) modifiable chez l’hébergeur ;
  • un serveur dédié au courrier, de préférence : il n’y a alors aucun autre service à surveiller sur cette machine, et une compromission d’une application web n’atteint pas vos boîtes.

Étape 1 : l’identité réseau, avant tout le reste

Les grands hébergeurs de messagerie vérifient que l’adresse IP qui se présente correspond, dans les deux sens, au nom annoncé. Réglez le PTR chez l’hébergeur du VPS (pas dans la zone DNS du domaine), pour IPv4 et pour IPv6 si le serveur en a une :

dig +short -x 203.0.113.25          # mail.example.org.
dig +short mail.example.org A       # 203.0.113.25
dig +short -x 2001:db8::25          # mail.example.org. (sinon, désactivez l'IPv6 sortant pour le courrier)

Un PTR IPv6 manquant est un piège courant : si le serveur a une adresse IPv6, il l’utilise pour joindre Gmail, et Gmail refuse le message faute de PTR sur cette adresse. Soit vous le réglez, soit vous empêchez mox d’envoyer en IPv6.

Étape 2 : installer

useradd -m -d /home/mox -s /sbin/nologin mox
cd /home/mox
# télécharger le binaire mox de la dernière version publiée, vérifier sa somme de contrôle
install -o root -g root -m 0755 mox-vX.Y.Z-linux-amd64 /home/mox/mox
./mox quickstart postmaster@example.org

quickstart fait beaucoup en une commande :

  • il écrit config/mox.conf (le serveur : nom d’hôte, adresses d’écoute, ACME) et config/domains.conf (les domaines, les comptes, les adresses) ;
  • il génère deux clés DKIM par domaine (une RSA, une Ed25519) ;
  • il crée le compte postmaster et affiche son mot de passe, ainsi que celui de l’interface d’administration ;
  • il imprime la liste exacte des enregistrements DNS à créer, et une unité systemd prête à l’emploi.

Conservez cette sortie dans un endroit sûr : elle contient des mots de passe et les valeurs DNS. mox tourne sous le compte mox, sans droits root, et obtient seulement par systemd la capacité d’écouter sur les ports inférieurs à 1024.

Étape 3 : le pare-feu

PortUsageOuvrir à
25/tcpSMTP : réception depuis les autres serveurs, et envoi vers euxtout le monde
465/tcpsoumission chiffrée (TLS direct) pour vos clients de messagerietout le monde
587/tcpsoumission avec STARTTLS (anciens clients, relais de vos autres serveurs)tout le monde ou vos serveurs
993/tcpIMAP chiffrétout le monde
80, 443/tcpACME (certificats), MTA-STS, autoconfiguration, webmail, administrationtout le monde
firewall-cmd --permanent --add-service={smtp,smtps,smtp-submission,imaps,http,https}
firewall-cmd --reload

Le port 143 (IMAP non chiffré) n’a pas besoin d’être ouvert : tous les clients modernes savent utiliser 993.

Étape 4 : les enregistrements DNS, un par un

mail.example.org.                 A      203.0.113.25
mail.example.org.                 AAAA   2001:db8::25
example.org.                      MX     10 mail.example.org.
example.org.                      TXT    "v=spf1 mx ip4:127.0.0.1 ip6:::1 ~all"
2026a._domainkey.example.org.     TXT    "v=DKIM1; k=ed25519; p=…"
2026b._domainkey.example.org.     TXT    "v=DKIM1; k=rsa; p=…"
_dmarc.example.org.               TXT    "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.org"
mta-sts.example.org.              CNAME  mail.example.org.
_mta-sts.example.org.             TXT    "v=STSv1; id=20261105T120000"
_smtp._tls.example.org.           TXT    "v=TLSRPTv1; rua=mailto:tlsrpt@example.org"
autoconfig.example.org.           CNAME  mail.example.org.
_autodiscover._tcp.example.org.   SRV    0 1 443 mail.example.org.
_submissions._tcp.example.org.    SRV    0 1 465 mail.example.org.
_imaps._tcp.example.org.          SRV    0 1 993 mail.example.org.
example.org.                      CAA    0 issue "letsencrypt.org"

Être trouvé : A, AAAA, MX

Le MX dit aux autres serveurs où livrer le courrier de example.org. Il pointe toujours vers un nom, jamais vers une adresse IP, et ce nom doit avoir ses enregistrements A (et AAAA). La priorité (10) ne sert que s’il y a plusieurs MX.

Prouver qui envoie : SPF, DKIM, DMARC

  • SPF liste les machines autorisées à envoyer pour le domaine. mx autorise les serveurs du MX ; ip4:127.0.0.1 ip6:::1 sert au courrier que le serveur s’envoie à lui-même (voir plus bas) ; ~all marque les autres comme suspects sans les rejeter. N’utilisez -all que si vous êtes certain de connaître toutes vos sources d’envoi (lettres d’information, formulaires de sites…) ;
  • DKIM publie les clés publiques qui permettent de vérifier la signature que mox pose sur chaque message sortant. Deux sélecteurs (2026a, 2026b) permettent de changer de clé sans coupure : on publie la nouvelle, on signe avec, puis on retire l’ancienne quelques semaines plus tard ;
  • DMARC dit aux destinataires quoi faire d’un message dont ni SPF ni DKIM ne sont alignés sur le domaine de l’expéditeur, et où envoyer leurs rapports. Commencez par p=none pendant une à deux semaines en lisant les rapports, passez à p=quarantine, puis à p=reject quand vous êtes sûr qu’aucun envoi légitime n’échoue.

Imposer le chiffrement : MTA-STS et TLS-RPT

Sans MTA-STS, un attaquant placé sur le chemin peut retirer l’offre STARTTLS d’une connexion SMTP et lire le courrier en clair. Avec MTA-STS, les serveurs qui vous écrivent apprennent que votre domaine exige TLS avec un certificat valide. mox sert lui-même la politique sur https://mta-sts.example.org/.well-known/mta-sts.txt. TLS-RPT vous fait envoyer chaque jour les rapports des échecs de chiffrement. Changez l’id de _mta-sts à chaque modification de la politique.

Configurer les clients : autoconfig et SRV

Thunderbird, l’application Mail d’Apple et d’autres trouvent seuls les bons serveurs et ports grâce à autoconfig, _autodiscover et aux enregistrements SRV. L’enregistrement CAA, facultatif, n’autorise que Let’s Encrypt à émettre des certificats pour le domaine.

Une commande imprime à tout moment les valeurs attendues : ./mox config dnsrecords example.org.

Étape 5 : démarrer, puis créer les comptes

systemctl enable --now mox
./mox config test
./mox config account add alice alice@example.org
./mox setaccountpassword alice
./mox config address add contact@example.org alice      # une adresse de plus pour le même compte
./mox config account list

Côté client de messagerie : IMAP sur mail.example.org:993 (SSL/TLS), envoi sur mail.example.org:465 (SSL/TLS) avec l’adresse complète comme identifiant. Le webmail et l’administration sont sur https://mail.example.org/.

Étape 6 : vérifier, sérieusement

./mox config dnscheck example.org     # SPF, DKIM, DMARC, MTA-STS, TLS-RPT, MX, PTR
./mox queue list                      # la file d'envoi : vide ou presque
journalctl -u mox -n 50 --no-pager
dig +short MX example.org @ns1.fournisseur-dns.example   # interrogez les serveurs faisant autorité

Interrogez toujours les serveurs DNS faisant autorité de votre zone : certains résolveurs publics renvoient des réponses vides trompeuses pendant la propagation, et on finit par corriger un problème qui n’existe pas.

Puis le test qui compte : envoyez un message vers une boîte Gmail et une boîte Outlook. Ouvrez l’en-tête complet (« Afficher l’original » dans Gmail) et cherchez spf=pass, dkim=pass et dmarc=pass. Répondez depuis ces boîtes et vérifiez que la réponse arrive. Les premiers jours, quelques messages peuvent tomber en indésirables le temps que votre adresse se fasse une réputation : demandez aux destinataires de les marquer comme légitimes.

Ce que donnent ces vérifications sur mon serveur mail

Mon propre serveur mox, vérifié le 2 novembre 2026. Les noms de domaine sont réécrits en example.org, les valeurs sont réelles.

# ./mox version
v0.0.17-go1.27.0
linux/amd64

# ./mox config test
config OK

# ss -ltn   (ports en écoute, mox seulement)
0.0.0.0:25  0.0.0.0:443  0.0.0.0:465  0.0.0.0:587  0.0.0.0:993   (et les mêmes sur [::])

# dig +short MX example.org
10 mail.example.org.
# dig +short TXT _dmarc.example.org
"v=DMARC1;p=reject;rua=mailto:dmarc-reports@example.org!10m"
# dig +short TXT _mta-sts.example.org
"v=STSv1; id=ansible20260915"
# dig +short TXT _smtp._tls.example.org
"v=TLSRPTv1; rua=mailto:tlsreports@example.org"

# openssl s_client -starttls smtp -connect mail.example.org:25 -servername mail.example.org
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Verify return code: 0 (ok)
  • config OK : les deux fichiers sont lisibles et cohérents. À lancer avant chaque redémarrage ; mox refuse de démarrer sur une configuration invalide, et un serveur mail qui ne redémarre pas, ce sont des messages qui s’accumulent chez les expéditeurs.
  • Cinq ports, en IPv4 et en IPv6 : 25 (réception depuis les autres serveurs), 465 et 587 (envoi par vos clients), 993 (IMAP), 443 (webmail, administration, politique MTA-STS et certificats automatiques). Le port 80 n’est pas ouvert : les certificats s’obtiennent sur le 443 avec le défi TLS-ALPN.
  • p=reject dans DMARC : n’y passez que lorsque les rapports agrégés montrent que toutes vos sources légitimes passent, sinon ce sont vos propres messages qui seront rejetés. Le suffixe !10m limite la taille des rapports à 10 Mo.
  • id=ansible20260915 dans l’enregistrement MTA-STS : l’identifiant signale aux expéditeurs que la politique a changé. Il faut le modifier à chaque changement du fichier de politique, sinon ils garderont l’ancienne en cache pendant des semaines.
  • TLSv1.3, Verify return code: 0 : STARTTLS sur le port 25 présente un certificat valide pour le nom du serveur. C’est ce que vérifie un serveur expéditeur quand MTA-STS est en mode « enforce ».

Le courrier que le serveur s’envoie à lui-même

Les rapports de cron, de logwatch ou des sauvegardes sont souvent adressés à root@example.org, hébergé sur ce même serveur. mox n’a pas de livraison locale interne : il cherche le MX, trouve son propre nom, et repasse par son interface publique. Cela échoue par intermittence. La correction consiste à router ce courrier par la boucle locale :

# domains.conf : router le courrier de nos propres domaines par la boucle locale
Routes:
	-
		ToDomain:
			- example.org
		Transport: loopback

# mox.conf
Transports:
	loopback:
		SMTP:
			Host: mail-loopback.example.org   # 127.0.0.1 dans /etc/hosts
			Port: 25
			STARTTLSInsecureSkipVerify: true

Deux conséquences à traiter. mox applique ses contrôles à ce courrier comme à n’importe quel autre : il faut donc ip4:127.0.0.1 ip6:::1 dans le SPF (sans risque, personne d’extérieur ne se connecte depuis la boucle locale). Et le compte qui ne reçoit que ce courrier interne doit avoir NoFirstTimeSenderDelay: true : sinon mox applique à ces expéditeurs « inconnus » un délai de quinze secondes que le client de la boucle n’attend pas.

Faire envoyer vos autres serveurs par mox

Vos autres machines ont besoin d’envoyer du courrier (alertes, formulaires PHP, rapports). Plutôt que d’en faire autant de serveurs de courrier mal vus, configurez sur chacune un Postfix minimal qui confie tout à mox, en s’authentifiant sur le port 587 avec un compte dédié :

# /etc/postfix/main.cf sur un AUTRE serveur, qui confie tout son courrier à mox
relayhost = [mail.example.org]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
inet_interfaces = loopback-only

inet_interfaces = loopback-only : ce Postfix n’écoute que localement, il ne reçoit jamais de courrier de l’extérieur. Sur une machine sous SELinux, PHP a besoin du booléen httpd_can_sendmail pour utiliser mail().

Sauvegarder et restaurer

./mox backup /data/backup/mox/$(date +%Y%m%d)
./mox verifydata /data/backup/mox/20261105

mox backup produit une copie cohérente des bases de comptes et des messages sans arrêter le service ; mox verifydata vérifie qu’elle est exploitable. Copiez chaque nuit la sauvegarde hors du serveur, avec les fichiers de configuration (qui contiennent les clés DKIM). Un serveur de courrier, c’est aussi une identité : sans les clés DKIM d’origine, il faudrait republier le DNS. Pour restaurer, on arrête mox, on remplace le répertoire de données par la sauvegarde, on lance verifydata, puis on redémarre.

Mettre à jour

Une mise à jour consiste à remplacer le binaire et à redémarrer. Lisez les notes de version avant : certaines versions renomment des options de configuration. Lancez une sauvegarde juste avant, puis ./mox config test avec le nouveau binaire avant de redémarrer le service.

Diagnostiquer un message refusé

  • Gmail refuse, « PTR » ou « reverse DNS » dans le message d’erreur : PTR absent ou incohérent, souvent en IPv6 ;
  • message en indésirables chez tout le monde : vérifiez que DKIM et DMARC passent, et l’adresse IP sur les listes de blocage ;
  • messages qui restent dans la file : ./mox queue list donne la dernière erreur de chaque message ; un délai d’attente vers tous les destinataires indique le port 25 sortant bloqué ;
  • refus pour spf-policy sur le courrier interne : il manque la boucle locale dans le SPF ;
  • les rapports DMARC arrivent chaque jour dans la boîte dmarc-reports : mox les lit et les présente dans son interface. C’est là qu’on découvre qu’un service tiers envoie en votre nom sans être autorisé.

Ce billet fait partie d’une série de tutoriels d’administration système (tag « pas à pas »).
Série « Pas à pas », tutoriel 8/77. · ← Tutoriel précédent · Tutoriel suivant → (à paraître le 6/11) · English version

Articles liés