Aller au contenu

Relai SMTP

Hors-prod — Mailcatcher

En environnement hors-prod, les applications utilisent Mailcatcher, un pod standalone déployé dans le namespace de l'application qui intercepte les e-mails sans les envoyer réellement.

Déploiement

La configuration se fait dans les Helm values de l'application. Une seule déclaration suffit par namespace, quel que soit le nombre de composants.

Compatible avec app-template-v2 et drupal-template.

standaloneMailcatcher:
  enabled: true
  image:
    repository: rg.fr-par.scw.cloud/namespace-scw-service/mailcatcher
    tag: latest
    pullPolicy: Always
  ingress:
    enabled: true
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-scaleway-dns01"
      traefik.ingress.kubernetes.io/router.middlewares: "int-APP_NAME-APP_NAME-ip-whitelist@kubernetescrd"
    host: int-APP_NAME-mailcatcher.direct.horsprod.ademe-scw.fr
    tls: int-APP_NAME-mailcatcher-direct-horsprod-ademe-scw-fr-tls

Variables d'environnement

Une fois Mailcatcher déployé, configurer les variables d'environnement de l'application (les noms exacts dépendent du framework) :

MAIL_HOST=APP_NAME-mailcatcher
MAIL_PORT=1025

À éviter — le mode sidecar

Ne pas utiliser mailcatcher.enabled: true

mailcatcher:
  enabled: true  # Ne pas faire
Cette option déploie Mailcatcher comme sidecar dans chaque pod de l'application, ce qui multiplie le nombre de containers par namespace.

Nous avons fait le choix de toujours privilégier standaloneMailcatcher : un seul pod dédié par namespace.

L'option sidecar sera supprimée de l'app-template-v2 une fois toutes les applications migrées.


Prod — Maddy

Contexte

Époque Solution Problème
Avant Postfix par namespace → SMTP DRI Un pod par namespace ; indisponible si le SMTP DRI est down
Tentative Scaleway TEM en direct Erreurs rencontrées
Aujourd'hui Maddy — mutualisé, cluster prod uniquement

Architecture

Application (cluster prod)
    ↓ SMTP port 25 (sans authentification)
smtp-maddy.prod-maddy-smtp.svc.cluster.local
    ↓                              ↓
Deployment DRI (6 replicas)   Deployment TEM (2 replicas)
smtp.ademe-dri.fr:25          smtp.tem.scaleway.com:587

Deux déploiements distincts sont exposés derrière le même service Kubernetes, ce qui répartit le trafic entre les deux relais selon le ratio de leurs replicas :

Déploiement Replicas Relai cible Ratio actuel
maddy-dri 6 smtp.ademe-dri.fr:25 ~75 %
maddy-tem 2 smtp.tem.scaleway.com:587 ~25 %

Le ratio est volontairement en faveur de DRI pour le moment : la réputation de l'IP TEM Scaleway est encore en construction. Une fois celle-ci établie, les replicas pourront être rééquilibrés à 50/50.

Sondes de disponibilité

Chaque déploiement est équipé de sondes liveness et readiness qui surveillent à la fois Maddy localement et le SMTP distant. Si le SMTP distant devient indisponible, les pods concernés sont automatiquement retirés du service — le trafic bascule entièrement sur l'autre déploiement.

custom_probes:
  liveness:
    exec:
      command:
        - /bin/sh
        - -c
        - 'echo QUIT | nc -w 5 localhost 25 | head -1 | grep -q "220"'
    initialDelaySeconds: 15
    periodSeconds: 30
    failureThreshold: 5
    successThreshold: 1
  readiness:
    exec:
      command:
        - /bin/sh
        - -c
        - 'echo QUIT | nc -w 5 smtp.ademe-dri.fr 25 | head -1 | grep -q "220"'
    periodSeconds: 15
    failureThreshold: 3
    successThreshold: 2
  • Liveness : vérifie que Maddy répond localement sur le port 25. En cas d'échec répété (5×), le pod est redémarré.
  • Readiness : vérifie que le SMTP distant répond. En cas d'échec (3×), le pod est retiré du service sans être redémarré — il reprend le trafic automatiquement dès que le SMTP distant revient.

Utilisation depuis une application

SMTP_HOST=smtp-maddy.prod-maddy-smtp.svc.cluster.local
SMTP_PORT=25

Aucune authentification requise — le cluster interne est considéré comme de confiance.

Configuration

Paramètre Description
maddy.hostname Nom d'hôte SMTP déclaré par le serveur
maddy.primary_domain Domaine principal déclaré dans le protocole SMTP
maddy.secondary_domains Domaines supplémentaires (séparés par des espaces)
maddy.tls_secret_name Secret Kubernetes contenant le certificat TLS
smtp_target_tem Activer le relai Scaleway TEM
smtp_target_dri Activer le relai ADEME DRI

Secrets

Gérés via External Secrets + Vault, rafraîchis automatiquement toutes les 5 minutes.

Secret Vault Contenu Usage
ademe/cluster-service/maddy users Credentials utilisateurs Maddy
ademe/service/tem_scaleway username_prod Login relai Scaleway TEM
ademe/service/maddy scw_api_secret Mot de passe relai Scaleway TEM

Avantages et limites

Postfix (avant) Maddy (maintenant)
Résilience Single point of failure par namespace Multi-replica, bascule automatique TEM / DRI
Mutualisation Un pod par namespace Un service partagé pour tout le cluster prod
Métriques par application Stats Postfix par application Non disponible — en cours

Métriques en cours de construction

La migration vers Maddy a supprimé les stats d'envoi par application qu'offraient les métriques Postfix. Des dashboards basés sur les logs Maddy sont en cours de construction.


TODO

  • Construire les dashboards de métriques à partir des logs Maddy
  • Migrer toutes les applications du mode sidecar vers standaloneMailcatcher
  • Supprimer l'option mailcatcher.enabled de l'app-template-v2 après migration complète
  • Équilibrer les replicas DRI/TEM à 50/50 une fois la réputation de l'IP TEM Scaleway établie