4.9 KiB
4.9 KiB
Intégration Mail — Vue d'ensemble
Fonctionnalités
- Lecture de la boîte mail partagée (IMAP) depuis Lesstime
- Navigation par dossiers (arbre récursif avec compteurs non-lus)
- Liste paginée des messages (infinite scroll, cursor-based)
- Lecture des corps de mail sanitisés (DOMPurify — protection XSS + pixels tracking)
- Création d'une tâche Lesstime depuis un mail (sujet → titre, texte → description)
- Lien mail ↔ tâche (bidirectionnel)
- Onglet "Mails" dans le TaskDrawer pour retrouver les mails liés à une tâche
- Synchronisation IMAP automatique via cron OS (toutes les 10 min)
- Déclenchement manuel de sync depuis l'UI (bouton Refresh)
- Badge non-lus en temps réel dans la sidebar (polling 30s)
Endpoints API
| Méthode | URL | Rôle | Description |
|---|---|---|---|
| GET | /api/mail/configuration |
ROLE_ADMIN | Lire la config singleton |
| PATCH | /api/mail/configuration |
ROLE_ADMIN | Mettre à jour la config |
| POST | /api/mail/configuration/test |
ROLE_ADMIN | Tester la connexion IMAP |
| GET | /api/mail/folders |
ROLE_USER | Arbre des dossiers + unread |
| GET | /api/mail/messages |
ROLE_USER | Liste paginée (param: folder, cursor, limit) |
| GET | /api/mail/messages/{id} |
ROLE_USER | Détail + body (cached 5 min) |
| POST | /api/mail/messages/{id}/read |
ROLE_USER | Marquer lu/non-lu |
| POST | /api/mail/messages/{id}/flag |
ROLE_USER | Marquer étoilé/non-étoilé |
| POST | /api/mail/messages/{id}/create-task |
ROLE_USER | Créer tâche depuis mail |
| POST | /api/mail/messages/{id}/link-task |
ROLE_USER | Lier mail à tâche existante |
| DELETE | /api/mail/messages/{id}/link-task/{taskId} |
ROLE_USER | Supprimer le lien |
| GET | /api/tasks/{id}/mails |
ROLE_USER | Mails liés à une tâche |
| GET | /api/mail/attachments/{id} |
ROLE_USER | Télécharger une pièce jointe |
| POST | /api/mail/sync |
ROLE_USER | Déclencher sync async (Messenger) |
Tous les endpoints /api/mail/* refusent explicitement ROLE_CLIENT.
Sécurité
- ROLE_CLIENT exclusif : accès refusé à tous les endpoints mail et à la page
/mail - Le sidebar "Messagerie" est masqué pour les ROLE_CLIENT
- Password IMAP chiffré via libsodium secretbox (env
ENCRYPTION_KEY) - Corps de mail sanitisés via DOMPurify (
sanitizeMailHtml.ts) — script/iframe/object/embed/on*/javascript: bloqués - Pixels tracking distants (img src http) remplacés par placeholder
- Aucun body, password ou contenu de pièce jointe dans les logs
Dépendances
Backend
webklex/php-imap: client IMAP PHPsymfony/lock: Symfony Lock pour éviter les syncs parallèlessymfony/messenger: dispatch asynchroneMailSyncRequestedlibsodium(ext PHP) : chiffrement du password IMAP
Frontend
dompurify+@types/dompurify: sanitization HTML des corps de mail
Fichiers clés
Backend
src/Entity/MailConfiguration.php— entité singleton (credentials, enabled)src/Entity/MailFolder.php— dossier IMAP syncedsrc/Entity/MailMessage.php— message IMAP synced (headers, flags)src/Entity/TaskMailLink.php— lien tâche ↔ mailsrc/Mail/ImapMailProvider.php— implémentation IMAP (webklex)src/Service/MailSyncService.php— algorithme de sync (UID FETCH, resync flags)src/Controller/Mail/— controllers custom (test, folders, messages, sync)src/State/Mail/— providers/processors API Platform (configuration)
Frontend
frontend/pages/mail.vue— page principale 3 colonnesfrontend/components/mail/— MailFolderTree, MailMessageList, MailMessageViewer, MailRefreshButtonfrontend/components/admin/AdminMailTab.vue— onglet config adminfrontend/stores/mail.ts— store Pinia (folders, messages, polling)frontend/services/mail.ts— service API (toutes les méthodes)frontend/services/dto/mail.ts— types TypeScriptfrontend/utils/sanitizeMailHtml.ts— DOMPurify wrapper
Synchronisation cron
Voir docs/mail-cron-setup.md pour la configuration détaillée.
Résumé :
# Cron OS (toutes les 10 min)
*/10 * * * * cd /path/to/Lesstime && make mail-sync >> /var/log/lesstime-mail-sync.log 2>&1
# Commandes Makefile
make mail-sync # Sync complète
make mail-sync FOLDER=INBOX # Sync d'un dossier
make mail-sync DRYRUN=1 # Simulation sans écriture
Configuration admin
- Aller sur
/admin→ onglet "Mail" - Renseigner les credentials IMAP/SMTP (OVH :
ssl0.ovh.net, port 993/465, SSL) - Cliquer "Tester la connexion"
- Activer la synchronisation → Enregistrer
- Configurer le cron OS
Variables d'environnement
| Variable | Description | Obligatoire |
|---|---|---|
ENCRYPTION_KEY |
Clé hex 32 bytes libsodium pour chiffrer le password IMAP | Oui |
LOCK_DSN |
DSN Symfony Lock (défaut: flock) |
Non |
MESSENGER_TRANSPORT_DSN |
Transport Messenger pour sync async | Recommandé (prod) |