Files
Lesstime/docs/mail-cron-setup.md
Matthieu 5da165f739 docs : corrige le déploiement prod (Docker) et documente les variables d'env mail
- README : section Variables d'environnement (ENCRYPTION_KEY, LOCK_DSN) + section Déploiement passée au flow Docker (deploy.sh)
- mail-cron-setup : sépare dev (make, php-lesstime-fpm) et prod (lesstime-app, docker compose exec), cron prod réel
- infra/prod/.env.example : ajoute ENCRYPTION_KEY et LOCK_DSN (manquaient, requis pour la sync mail)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:48:55 +02:00

4.8 KiB

Mail Integration — Configuration cron OS

Vue d'ensemble

La synchronisation IMAP est déclenchée par un cron OS toutes les 10 minutes. Elle appelle la commande Symfony app:mail:sync qui s'exécute dans le container PHP.

Un Symfony Lock (mail.sync, TTL 10 min, store flock via LOCK_DSN=flock) empêche les runs de se chevaucher si une sync prend plus de 10 min.

Dev vs prod — en dev le container s'appelle php-lesstime-fpm et on passe par make. En production le container s'appelle lesstime-app (service app du docker-compose.yml dans /var/www/lesstime), il n'y a pas de make : tout passe par docker compose / docker exec.

Prérequis

  • MailConfiguration.enabled = true (configurable depuis l'admin — onglet « Mail »)
  • ENCRYPTION_KEY (clé hex 32 bytes) défini dans l'environnement :
    • dev : infra/dev/.env.docker.local
    • prod : /var/www/lesstime/.env
  • Container démarré :
    • dev : make start (container php-lesstime-fpm)
    • prod : déployé via sudo ./deploy.sh (container lesstime-app)

Variables d'environnement nécessaires

Variable Description Exemple
ENCRYPTION_KEY Clé hex 32 bytes pour déchiffrer le password IMAP $(php -r "echo bin2hex(random_bytes(32));")
LOCK_DSN DSN du store de verrous Symfony flock (défaut, fichier local)

La clé ENCRYPTION_KEY doit être identique à celle utilisée pour chiffrer le password lors de la configuration depuis l'admin. Si elle change, les credentials stockés deviennent illisibles.


Dev

Lancer une sync à la main

make mail-sync                  # sync complète (toutes les boîtes)
make mail-sync FOLDER=INBOX     # un seul dossier (doit déjà exister en base)
make mail-sync DRYRUN=1         # simulation (dry-run, pas d'écriture BDD)

Ou directement dans le container :

docker exec php-lesstime-fpm php bin/console app:mail:sync
docker exec php-lesstime-fpm php bin/console app:mail:sync --folder=INBOX
docker exec php-lesstime-fpm php bin/console app:mail:sync --dry-run

Logs (dev)

make logs-dev    # tail -f var/log/dev.log

Les messages loggés par MailSyncService sont préfixés mail.sync.


Production

En prod, l'app tourne dans le container lesstime-app déployé par sudo ./deploy.sh (dossier /var/www/lesstime). La commande s'exécute en tant que www-data (uid 33), comme les migrations lancées par deploy.sh.

Lancer une sync à la main

Depuis /var/www/lesstime :

sudo docker compose exec -T -u www-data app php bin/console app:mail:sync
sudo docker compose exec -T -u www-data app php bin/console app:mail:sync --folder=INBOX
sudo docker compose exec -T -u www-data app php bin/console app:mail:sync --dry-run

Installer le cron

Sur la machine hôte (pas dans le container). Comme docker requiert sudo en prod, installer le cron sous root :

sudo crontab -e

Ajouter :

*/10 * * * * cd /var/www/lesstime && docker compose exec -T -u www-data app php bin/console app:mail:sync >> /var/log/lesstime-mail-sync.log 2>&1

Le crontab de root exécute déjà les commandes en root → pas de sudo à l'intérieur de la ligne cron. La commande est idempotente (UIDs uniques en base) : la relancer ne duplique pas les données.

Logs (prod)

cd /var/www/lesstime
docker compose logs -f --tail=100 app           # logs container
docker compose exec app cat var/log/prod.log    # log Symfony (volume lesstime_logs)

Checklist setup production

  1. Définir ENCRYPTION_KEY (hex 32 bytes) et LOCK_DSN=flock dans /var/www/lesstime/.env
  2. Créer le compte mail dédié (ex: lesstime@votre-domaine.fr) chez OVH
  3. Accéder à /admin → onglet « Mail » → renseigner les credentials IMAP/SMTP
  4. Cliquer « Tester la connexion » → vérifier le succès
  5. Cocher « Activer la synchronisation » → Enregistrer
  6. Lancer une sync manuelle pour valider (commande ci-dessus)
  7. Installer le cron OS (voir « Installer le cron »)
  8. Vérifier les logs après la première sync (docker compose logs -f app, chercher mail.sync)

Sécurité

  • Le password IMAP est toujours stocké chiffré (libsodium secretbox)
  • Les corps de mails, passwords et pièces jointes ne sont jamais loggés
  • Le lock flock évite les runs parallèles (fichier dans /tmp/sf.mail.sync.<hash>.lock)
  • La page /mail et tous les endpoints /api/mail/* sont refusés aux ROLE_CLIENT exclusifs
  • Le sidebar « Messagerie » est masqué pour les utilisateurs ROLE_CLIENT sans ROLE_USER
  • Les corps de mails sont sanitisés via DOMPurify avant affichage (frontend/utils/sanitizeMailHtml.ts)
  • Les pixels de tracking distants sont remplacés par un placeholder