Aller au contenu

Integration

Le service de messagerie interagit avec de nombreux composants de l'infrastructure. Ce chapitre detaille les integrations cles.

Integration IAM : LDAP et OIDC avec Keycloak

Provisioning des utilisateurs via LDAP

Keycloak expose un annuaire LDAP (ou s'interface avec FreeIPA). Stalwart interroge cet annuaire pour résoudre les comptes email :

graph LR
    Stalwart["Stalwart"] -->|LDAPS:636<br/>Recherche user<br/>Verification pwd| Keycloak["Keycloak<br/>(LDAP)"]
    Keycloak --> FreeIPA["FreeIPA /<br/>base users"]

Configuration LDAP détaillée

# /opt/stalwart/config/config.toml

[directory.ldap]
type = "ldap"
url = "ldaps://iam.enterprise.internal.company.io:636"
base-dn = "dc=company,dc=io"
timeout = "10s"

[directory.ldap.bind]
dn = "cn=stalwart,ou=services,dc=company,dc=io"
secret = "%{env:LDAP_BIND_PASSWORD}%"

[directory.ldap.filter]
name = "(&(objectClass=inetOrgPerson)(uid=?))"
email = "(&(objectClass=inetOrgPerson)(|(mail=?)(mailAlias=?)))"
verify = "(&(objectClass=inetOrgPerson)(|(mail=?)(mailAlias=?)))"
expand = "(&(objectClass=groupOfNames)(mail=?))"
domains = "(&(objectClass=domain)(dc=?))"

[directory.ldap.attributes]
name = "uid"
class = "objectClass"
description = "cn"
secret = "userPassword"
email = "mail"
email-alias = "mailAlias"
quota = "mailQuota"
groups = "memberOf"

Attributs LDAP requis dans Keycloak

Attribut LDAP Type Exemple Usage Stalwart
uid Requis alice Identifiant de connexion
mail Requis alice@company.io Adresse email principale
mailAlias Optionnel a.dupont@company.io Alias email
mailQuota Optionnel 5368709120 (5 Go en octets) Quota de la boite
memberOf Auto cn=dev,ou=groups,... Appartenance aux groupes

SSO webmail via OIDC

Pour permettre l'accès au webmail ou a JMAP sans re-saisie du mot de passe :

[directory.oidc]
type = "oidc"
issuer-url = "https://iam.enterprise.internal.company.io/realms/company"
client-id = "stalwart-mail"
client-secret = "%{env:OIDC_CLIENT_SECRET}%"
scope = "openid email profile"

Configuration du client OIDC dans Keycloak

Parametre Valeur
Client ID stalwart-mail
Client Protocol openid-connect
Access Type confidential
Valid Redirect URIs https://mail.company.io/*
Web Origins https://mail.company.io
Standard Flow Enabled On
Direct Access Grants On (pour les clients IMAP/SMTP legacy)

Flux d'authentification

sequenceDiagram
    participant U as Utilisateur
    participant W as Webmail/JMAP
    participant S as Stalwart
    participant K as Keycloak
    U->>W: Acces webmail
    W->>S: Redirect OIDC
    S->>K: AuthZ request
    K->>U: Page de login Keycloak
    U->>K: Identifiants
    K->>U: Code d'autorisation
    S->>K: Token request
    K->>S: JWT token
    S->>W: Session JMAP
    W->>U: Webmail charge

Integration DNS via CoreDNS

Enregistrements MX dans les zones internes

Pour le routage des emails internes (entre services), ajouter les enregistrements MX dans la zone interne :

; Zone enterprise.internal.company.io
; Serveur de messagerie interne
enterprise.internal.company.io.  300  IN  MX  10  mail.enterprise.internal.company.io.
mail.enterprise.internal.company.io.  300  IN  A  10.20.1.30

; Autoconfig interne
autoconfig.enterprise.internal.company.io.  300  IN  CNAME  mail.enterprise.internal.company.io.

Split-horizon pour le mail

Le DNS interne résout mail.company.io vers l'IP privee, evitant le NAT hairpin :

; Vue interne (CoreDNS)
mail.company.io.  300  IN  A  10.20.1.30

; Vue externe (DNS public)
mail.company.io.  300  IN  A  203.0.113.10

Monitoring avec Prometheus et Grafana

Metriques exposees par Stalwart

Stalwart expose des metriques Prometheus sur le endpoint HTTP :

# Recuperer les metriques
curl -s http://localhost:8080/metrics

Metriques principales :

Metrique Type Description
mail_incoming_total Counter Nombre total d'emails reçus
mail_outgoing_total Counter Nombre total d'emails envoyes
mail_delivery_total Counter Livraisons reussies/échouées
mail_queue_size Gauge Nombre d'emails en file d'attente
mail_queue_age_seconds Histogram Âge des emails dans la queue
mail_spam_total Counter Emails détectés comme spam
mail_dkim_verify_total Counter Verifications DKIM (pass/fail)
mail_dmarc_verify_total Counter Verifications DMARC (pass/fail)
mail_tls_total Counter Connexions TLS (succès/echec)
mail_auth_total Counter Authentifications (succès/echec)
mail_connections_active Gauge Connexions SMTP/IMAP actives
mail_storage_used_bytes Gauge Stockage utilise par les boites

Configuration Prometheus

# prometheus.yml
scrape_configs:
  - job_name: "stalwart-mail"
    scrape_interval: 30s
    static_configs:
      - targets: ["mail.enterprise.internal.company.io:8080"]
    metrics_path: /metrics

Dashboard Grafana

Les panneaux essentiels pour un dashboard de messagerie :

Panneau Metrique Type Seuil d'alerte
Emails reçus/min rate(mail_incoming_total[5m]) Graph
Emails envoyes/min rate(mail_outgoing_total[5m]) Graph
Taille de la queue mail_queue_size Gauge > 100 (warning)
Taux de livraison rate(mail_delivery_total{status="success"}[1h]) / rate(mail_delivery_total[1h]) Gauge < 95% (critical)
Ratio spam rate(mail_spam_total[1h]) / rate(mail_incoming_total[1h]) Gauge > 50% (warning)
Echecs DKIM rate(mail_dkim_verify_total{result="fail"}[1h]) Graph > 10% (warning)
Echecs TLS rate(mail_tls_total{result="fail"}[1h]) Graph > 5% (warning)
Connexions actives mail_connections_active Gauge > 500 (warning)
Stockage utilise mail_storage_used_bytes Gauge > 80% capacité

Regles d'alerte

# alerting-rules.yml
groups:
  - name: mail-alerts
    rules:
      - alert: MailQueueBacklog
        expr: mail_queue_size > 100
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "File d'attente mail anormalement grande ({{ $value }} messages)"

      - alert: MailQueueCritical
        expr: mail_queue_size > 500
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "File d'attente mail critique  {{ $value }} messages bloques"

      - alert: MailDeliveryRateLow
        expr: |
          (
            rate(mail_delivery_total{status="success"}[1h])
            / rate(mail_delivery_total[1h])
          ) < 0.95
        for: 30m
        labels:
          severity: critical
        annotations:
          summary: "Taux de livraison sous 95%  probleme de deliverabilite"

      - alert: MailQueueAgeTooOld
        expr: histogram_quantile(0.95, mail_queue_age_seconds_bucket) > 3600
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Des emails sont en queue depuis plus d'une heure"

      - alert: MailSpamRatioHigh
        expr: |
          rate(mail_spam_total[1h]) / rate(mail_incoming_total[1h]) > 0.5
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "Plus de 50% du trafic entrant est du spam"

Integration CalDAV

Calendrier et contacts intégrés

Stalwart expose un serveur CalDAV/CardDAV natif sur le même endpoint HTTP :

Endpoint Protocole Usage
https://mail.company.io/.well-known/caldav CalDAV Découverte calendrier
https://mail.company.io/.well-known/carddav CardDAV Découverte contacts
https://mail.company.io/dav/ WebDAV Racine DAV

Configuration des clients

Client Configuration CalDAV
Thunderbird Auto-découverte via mail.company.io
Apple Calendar Ajouter compte CalDAV mail.company.io
GNOME Calendar Compte en ligne → Nextcloud/CalDAV
DAVx5 (Android) URL: https://mail.company.io/.well-known/caldav

Invitations par email (iMIP)

Stalwart traite automatiquement les invitations de calendrier reçues par email :

  1. Un email contenant un piece jointe .ics (invitation) arrive
  2. Stalwart détecte le format iCalendar
  3. L'invitation est ajoutee au calendrier CalDAV de l'utilisateur
  4. L'utilisateur peut accepter/refuser via son client CalDAV
  5. La réponse est envoyee par email a l'organisateur
# Activer le traitement automatique des invitations
[jmap.calendar]
auto-schedule = true

Listes de diffusion

Configuration des listes dans Stalwart

Les listes de diffusion sont configurees comme des groupes dans l'annuaire LDAP ou via l'API :

# Creer une liste de diffusion
curl -X POST http://localhost:8080/api/principal \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "list",
    "name": "dev-team",
    "emails": ["dev@company.io"],
    "members": [
        "alice@company.io",
        "bob@company.io",
        "charlie@company.io"
    ]
  }'

Types de listes

Type Configuration Comportement
Discussion type: list Tous les membres peuvent poster
Announce type: list + ACL de soumission Seuls les admins peuvent poster
Alias type: alias Simple redirection, pas de list headers

En-têtes de liste

Stalwart ajoute automatiquement les en-têtes de liste standards :

List-Id: <dev.company.io>
List-Post: <mailto:dev@company.io>
List-Unsubscribe: <mailto:dev+unsubscribe@company.io>
List-Archive: <https://lists.company.io/dev/>

Integration LDAP pour les listes

Les groupes LDAP peuvent etre mappes directement en listes de diffusion :

[directory.ldap.filter]
expand = "(&(objectClass=groupOfNames)(mail=?))"

[directory.ldap.attributes]
members = "member"

Un groupe LDAP cn=dev,ou=groups,dc=company,dc=io avec l'attribut mail=dev@company.io et des member=uid=alice,... sera automatiquement traite comme une liste de diffusion par Stalwart.

Synthese

L'integration de Stalwart dans l'ecosysteme d'infrastructure repose sur trois axes : l'IAM (LDAP pour les comptes, OIDC pour le SSO), l'observabilité (Prometheus/Grafana avec alertes sur la queue et la deliverabilite), et les services complementaires (CalDAV pour les calendriers, listes de diffusion via groupes LDAP). Le chapitre suivant traite de la confidentialite et de la protection des données transportees par email.