- Added support for managing AI models within the AI assistant settings. - Introduced new hosted mail setup component for streamlined email configuration. - Updated environment variables for local development and proxy settings. - Enhanced error handling and user feedback in the chat page for API connectivity issues. - Improved routing for AI-related API calls in the Next.js configuration. - Added documentation for local development and agent management in CLAUDE.md.
9.3 KiB
Ultimail
Client mail unifié multi-comptes avec backend de synchronisation, frontend web (Next.js) et desktop (Tauri).
Vision & positionnement
Alternative souveraine à Gmail et Google Suite. L'interface s'inspire fortement de Google pour que les utilisateurs ne soient pas dépaysés et conservent leurs habitudes tout en migrant progressivement leur infrastructure vers cette solution.
Objectifs clés
- Parité fonctionnelle — supporter un maximum de fonctionnalités utiles des suites mail existantes (Gmail, Outlook)
- Au-delà de Gmail — fonctionnalités de pointe absentes ou limitées chez les géants : connectivité contrôlée avec agents IA, bots, webhooks avancés avec templates
- Expérience uniforme cross-plateforme — même UX sur desktop web, desktop app (Tauri) et mobile, avec les détails d'implémentation qui rendent cette uniformité possible
- Migration progressive — un utilisateur peut rattacher ses comptes existants et migrer à son rythme
Architecture
┌─────────────────────────────────────────────────────────┐
│ Clients (frontend) │
│ ├─ Web — Next.js 16 / React 19 (ce repo) │
│ └─ Desktop — Tauri (wrapper du même frontend) │
├─────────────────────────────────────────────────────────┤
│ Backend (futur) │
│ ├─ Client IMAP/POP3 + SMTP (collecte & envoi) │
│ ├─ Moteur de règles (tri, forward, réponses auto) │
│ ├─ Scheduler (envoi programmé, actions différées) │
│ ├─ API REST/WS pour sync clients │
│ └─ API tokens fine-grained (agents IA, webhooks) │
├─────────────────────────────────────────────────────────┤
│ Database — PostgreSQL │
│ ├─ Mails + métadonnées complètes + méta Ultimail │
│ ├─ Identifiants connexion serveurs mail │
│ ├─ Comptes Ultimail, préférences, libellés, dossiers │
│ ├─ Règles de tri, webhooks, tokens API │
│ └─ Auth comptes Ultimail │
└─────────────────────────────────────────────────────────┘
Modèle de domaine
Compte Ultimail vs Compte mail
| Concept | Description |
|---|---|
| Compte Ultimail | Compte utilisateur sur la plateforme. Possède préférences, libellés unifiés, règles, auth. |
| Compte mail | Connexion SMTP/IMAP ou POP3 vers un serveur/fournisseur. Un compte Ultimail en gère plusieurs. |
| Identité d'envoi | Adresse "From" utilisée pour envoyer. Peut différer du compte mail d'envoi (alias, catch-all). |
| Identité de réception | Adresse de destination. Peut différer du compte mail de réception (catch-all, routing). |
Relations clés
- 1 compte Ultimail → N comptes mail (envoi et/ou réception)
- 1 compte mail → N identités d'envoi / réception (catch-all, alias)
- Adresse de réception ≠ nécessairement le compte mail de réception (liées mais distinctes)
- Adresse d'envoi ≠ nécessairement le compte mail d'envoi (envoi via un autre serveur)
- Libellés et dossiers unifiés cross-comptes au niveau du compte Ultimail
Backend — Responsabilités (futur)
Synchronisation & collecte
- Client IMAP/SMTP permanent (toujours en ligne, même clients offline)
- Collecte des mails de tous les comptes mail rattachés
- Sync bidirectionnelle avec les clients (web/Tauri)
- Configuration unique propagée à tous les clients
Règles de tri & automatisations
- Règles de tri à la réception (conditions → actions)
- Envoi programmé (schedule pour le lendemain, etc.)
- Réponses automatiques
- Forward automatique
- Webhooks à la réception selon règles
Intégrations IA & programmatiques
- Tri par LLM (fournisseurs OpenAI-compatibles) avec contexte/prompt personnalisé par règle
- Tokens API fine-grained : accès partiel pour agents IA (lire certains mails, envoyer, catégoriser)
- Comportements programmatiques personnalisés par l'utilisateur
Stockage (PostgreSQL)
- Mails complets + métadonnées originales + métadonnées Ultimail (libellés, dossiers, statuts)
- Identifiants de connexion aux serveurs mail (chiffrés)
- Réglages comptes Ultimail, préférences d'organisation
- Règles de tri, webhooks, tokens API, auth
Frontend — Responsabilités (actuel)
Web (Next.js 16 — ce repo)
- Interface mail complète (liste, lecture, composition, recherche, contacts)
- Navigation URL-driven (
/mail/{folder},/mail/search,/contacts) - État persisté côté client (Zustand + localStorage) — sera remplacé par sync backend
- Mock data actuellement (
lib/email-data.ts,lib/contacts/mock-data.ts)
Desktop (Tauri — futur)
- Même frontend wrappé dans Tauri
- Accès natif (notifications, raccourcis système, stockage local)
Réglages & règles
Tous les réglages sont gérables depuis l'interface settings d'Ultimail :
Niveaux de configuration
- Global (compte Ultimail) — libellés unifiés, préférences d'affichage, densité, thème
- Par identité mail — signature, nom affiché, réponse par défaut, règles spécifiques
Types de règles
- Tri automatique (conditions sur expéditeur, sujet, contenu → libellé, dossier, archive)
- Forward automatique
- Réponse automatique
- Envoi programmé
- Webhook (POST vers URL externe à la réception)
- Tri IA (prompt + contexte personnalisé, fournisseur LLM configurable)
- Actions API (tokens fine-grained pour agents externes)
Webhooks — système de templates
Les webhooks supportent un format de payload personnalisable via templates réutilisables.
Principe : l'utilisateur définit un template (ex: "Slack", "Discord", "Custom") qui décrit le JSON à envoyer, avec des variables interpolées depuis le mail déclencheur.
Variables disponibles (exemples) :
$sender.name, $sender.email
$subject
$body.textContent, $body.htmlContent
$date, $timestamp
$recipients.to, $recipients.cc
$attachments.count, $attachments.names
$labels, $folder
$account.email (identité de réception)
Exemple — template Slack :
{
"text": "Nouveau mail de $sender.name",
"blocks": [
{
"type": "section",
"text": { "type": "mrkdwn", "text": "*$subject*\nDe: $sender.email\n$body.textContent" }
}
]
}
Cela permet de brancher n'importe quel service (Slack, Discord, n8n, Make, custom) sans code, juste en adaptant le template JSON et l'URL du webhook.
Stack technique (actuel)
| Couche | Choix |
|---|---|
| Framework | Next.js 16 (App Router, standalone) |
| UI | React 19, TypeScript 5.7 |
| Styles | Tailwind CSS 4, shadcn/ui (Radix, style new-york) |
| État | Zustand 5 (persist JSON debounced) |
| Éditeur riche | TipTap 3 |
| Icônes | @iconify/react, lucide-react |
| Recherche client | fuse.js |
| Package manager | pnpm |
| Deploy | Docker multi-stage → Node 22 Alpine, CapRover |
Conventions
Navigation
- URL = source de vérité (dossier, onglet inbox, page, message ouvert)
useMailRoute+lib/mail-url.tspour parsing/building- Recherche via query params sur
/mail/search
Stores (Zustand)
- Persistés : mail-store, mail-settings-store, nav-store, account-store, scheduled-store
- Éphémères : mail-search-store, mail-ui-store
- Ne pas persister l'UI éphémère sauf besoin produit explicite
Composants (components/gmail/)
- Organisation par feature :
compose/,email-list/,email-view/,sidebar/,mail-search/,contacts/ - Re-exports publics à la racine (
email-list.tsx→email-list/) - Hooks dédiés par domaine dans chaque feature
Docs internes
components/gmail/README.md— arborescence composantslib/stores/README.md— architecture stores
Environnement local & agents
Stack dev typique : nginx (:80) → ultid (Docker) + frontend Next.js (pnpm dev, proxy /api/v1 via ULTI_PROXY_ORIGIN).
Les agents doivent redémarrer les services eux-mêmes quand un changement l'exige — ne pas demander au développeur de le faire.
| Changement | Action (depuis ulti-backend/) |
|---|---|
Code Go (internal/, cmd/, migrations embarquées) |
./deploy/compose-up.sh up -d --build ultid |
Variable .env lue au démarrage d'ultid |
./deploy/compose-up.sh up -d --build ultid (régénère .env.resolved) |
| Module Compose optionnel (OpenWebUI, Nextcloud, …) | ./deploy/compose-up.sh up -d (overlay activé selon .env) |
| Redémarrage simple sans rebuild | ./deploy/compose-up.sh restart ultid |
| Frontend Next.js (ce repo) | pnpm dev se recharge seul ; rebuild seulement si config Next/env change |
Après restart backend, vérifier : curl -s http://127.0.0.1:80/api/v1/ai/config (JSON, pas 502).
Repo backend : ../ulti-backend — voir aussi ulti-backend/CLAUDE.md.