# 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 :
```json
{
  "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.ts` pour 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 composants
- `lib/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`.

### Mobile (Tauri 2 — Android + iOS)

Workspace : `mobile/` — voir `mobile/README.md` (build, Phase 0, scaffolds natifs).

**Toolchain Rust : utiliser rustup, pas Homebrew.** Sur macOS, Rust peut coexister via `brew install rust` (`/opt/homebrew/bin`) et rustup (`~/.cargo/bin`). Pour Tauri mobile, **toujours** la toolchain rustup :

- Vérifier avant tout `cargo` / `pnpm tauri` :
  ```bash
  which rustc cargo   # attendu : ~/.cargo/bin/rustc et ~/.cargo/bin/cargo
  rustc --version
  ```
- Si `which rustc` pointe vers `/opt/homebrew/bin/rustc`, recharger le shell (`source "$HOME/.cargo/env"`) ou placer `~/.cargo/bin` **avant** `/opt/homebrew/bin` dans le `PATH`.
- Cibles mobiles (une fois) :
  ```bash
  rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
  rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
  ```

Build frontend mobile (prérequis à chaque app Tauri) : `pnpm build:mobile` → `./out`.  
Compile Rust : `cd mobile && cargo check`.

Commandes Tauri (layout imbriqué `mobile/apps/<id>/src-tauri`) :

```bash
pnpm tauri:ultimail android init   # pas pnpm tauri --config depuis la racine
pnpm tauri:ultimail android dev
```

Les agents ne doivent **pas** supposer que le Rust Homebrew suffit pour les builds Android/iOS.
