Funk-lab/admin/infra/email.md

4.6 KiB

Email — Relay SMTP via Postfix → Gmail

Architecture

Hermes / AlertManager / cron / kubectl
        │
        ▼
  Postfix (storage-01 :25)
  smtp_generic_maps → réécrit l'expéditeur en aliyesilkaya93@gmail.com
        │  SASL + TLS (App Password)
        ▼
  smtp.gmail.com:587
        │
        ▼
    aliyesilkaya93@gmail.com

Postfix est configuré en relay-only sur storage-01 : aucune livraison locale, tous les mails transitent vers Gmail SMTP. Les réseaux autorisés à relayer : 127.0.0.0/8, 192.168.10.0/24, pods k8s (10.42.0.0/16), services k8s (10.43.0.0/16).

Pourquoi Gmail et pas Brevo ? Brevo exige de posséder un domaine vérifié (SPF/DKIM) pour relayer. Gmail SMTP avec App Password ne nécessite aucun domaine.


Prérequis — Google App Password

La vérification en 2 étapes Google doit être activée sur le compte.

  1. myaccount.google.com → Sécurité → Validation en 2 étapes → Activer
  2. myaccount.google.com/apppasswords → Nouveau → nom funk-postfix → Créer
  3. Google génère un code 16 caractères (ex: abcd efgh ijkl mnop) — c'est le mot de passe SMTP

Installation

1. Ajouter le App Password dans le vault

make vault-edit

Modifier ou ajouter :

vault_postfix_relay_password: "xxxx xxxx xxxx xxxx"   # App Password Google 16 caractères (avec espaces, OK)
make vault-encrypt

2. Vérifier les vars gateway

Dans ansible/group_vars/gateway/vars.yml :

postfix_relay_host: smtp.gmail.com
postfix_relay_port: 587
postfix_relay_user: "aliyesilkaya93@gmail.com"
postfix_sender_email: "aliyesilkaya93@gmail.com"

3. Déployer

make apply-storage
# ou cibler uniquement le rôle :
ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags postfix_relay

Vérification

Test depuis storage-01

echo "Test Funk Lab - $(date)" | sudo mail -s "[Funk] Test postfix" aliyesilkaya93@gmail.com

Suivre les logs en temps réel

sudo journalctl -u postfix -f --no-pager --output=cat

Résultat attendu : status=sent (250 2.0.0 OK ... - gsmtp)

Vérifier / vider la file d'attente

sudo mailq                  # lister les mails en attente
sudo postqueue -f           # forcer le flush
sudo postsuper -d ALL       # vider la queue (mails échoués)

Vérifier la réécriture expéditeur

sudo postconf smtp_generic_maps
sudo cat /etc/postfix/generic

Utilisation depuis les services

Depuis storage-01 (shell / cron / Hermes)

echo "Corps du mail" | sudo mail -s "[Funk] Sujet" aliyesilkaya93@gmail.com

Via Python (dans un skill Hermes) :

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg['Subject'] = '[Funk] Alerte'
msg['From'] = 'aliyesilkaya93@gmail.com'
msg['To'] = 'aliyesilkaya93@gmail.com'
msg.set_content('Contenu du mail')

with smtplib.SMTP('127.0.0.1', 25) as s:
    s.send_message(msg)

Depuis AlertManager (k8s)

Dans k8s/infra/monitoring/values.yaml :

alertmanager:
  config:
    receivers:
      - name: email
        email_configs:
          - to: aliyesilkaya93@gmail.com
            from: aliyesilkaya93@gmail.com
            smarthost: "192.168.10.1:25"
            require_tls: false   # TLS géré par Postfix vers Gmail, pas sur le LAN interne
    route:
      receiver: email

Depuis n'importe quel pod k8s

SMTP relay accessible sur 192.168.10.1:25 depuis tout le cluster.


Dépannage

Symptôme Cause probable Action
Connection refused sur :25 postfix non démarré sudo systemctl status postfix
Relay access denied IP source hors mynetworks sudo postconf mynetworks
Authentication failed App Password révoqué ou 2FA désactivé Régénérer dans myaccount.google.com/apppasswords
Mail jamais reçu Réécriture expéditeur manquante Vérifier /etc/postfix/generic et postconf smtp_generic_maps
Mail en spam Expéditeur non reconnu Normal si From ≠ aliyesilkaya93@gmail.com
Queue bloquée Ancien mail échoué en retry sudo postsuper -d ALL puis retester

Configuration Ansible

  • Rôle : ansible/roles/postfix_relay/
  • Vars : ansible/group_vars/gateway/vars.ymlpostfix_relay_*, postfix_sender_email
  • Secret : vault_postfix_relay_password dans ansible/group_vars/all/vault.yml
  • Templates : main.cf.j2, sasl_passwd.j2
  • Sender rewrite : /etc/postfix/generic (déployé par le rôle, postmap automatique)
  • nftables : port 25 ouvert automatiquement depuis 192.168.10.0/24