123 lines
6.2 KiB
Markdown
123 lines
6.2 KiB
Markdown
# MAIL-BROWSER-HERMES-TT
|
|
|
|
Runbook du service de lecture/reponse mail O365 pour hermes-tt, via un
|
|
navigateur Edge deja authentifie tournant dans le conteneur
|
|
`hermes-mail-browser` (session MFA maintenue cote serveur).
|
|
|
|
## Architecture
|
|
|
|
- Conteneur : `hermes-mail-browser` (reseau Docker `n8n`)
|
|
- API interne : `http://hermes-mail-browser:8000` (joignable par
|
|
`hermes-agent-tt` sur le meme reseau, pas besoin du port 3110 expose)
|
|
- noVNC : port 8810 (LAN uniquement) — pour reconnexion manuelle O365/MFA
|
|
- Envoi des projets de reponse : SMTP ik.me vers la boite pro de Nabil
|
|
(nabil.derouiche@tunisietelecom.tn)
|
|
|
|
## Statut — Phase 2 : COMPLETE (deployee et testee avec succes)
|
|
|
|
Endpoints construits, deployes et testes le 2026-07-23 :
|
|
|
|
- `GET /health` — conteneur sain, `authenticated: true`
|
|
- `GET /inbox?limit=N` — liste (expediteur / objet / heure / apercu) ;
|
|
`aria_label` contient "pieces jointes" si le mail en a
|
|
- `GET /message/{index}` — corps texte complet du mail
|
|
- `GET /message/{index}/attachments` — teste : liste des PJ, OK
|
|
- `GET /message/{index}/attachments/{filename}/text` — teste sur .docx ET
|
|
.pdf, extraction correcte confirmee (extraction auto PDF/DOCX/XLSX)
|
|
- `POST /draft-reply` `{"subject":"...","body_text":"..."}` — teste : mail
|
|
reellement recu dans la boite O365 pro. Envoie un PROJET vers la boite de
|
|
Nabil (jamais vers le correspondant). Prefixe de sujet
|
|
`[REPONSE PROPOSEE] Re: <objet>` ajoute automatiquement par l'API.
|
|
- Reseau : `hermes-agent-tt` joint `http://hermes-mail-browser:8000/health`
|
|
sans probleme (meme reseau Docker `n8n`) — teste, OK.
|
|
|
|
## Skill hermes-tt
|
|
|
|
`/opt/data/skills/mail-o365-tt.md` (dans `hermes-agent-tt`) reecrit le
|
|
2026-07-23 : les anciennes sections "ENVOI MAIL — SMTP Infomaniak" et
|
|
"LECTURE MAIL — OWA Navigateur" (methode `browser_snapshot`, obsolete car
|
|
bloquee par le MFA) ont ete entierement remplacees par des instructions
|
|
pointant vers l'API ci-dessus. Regle centrale conservee : hermes-tt ne
|
|
repond JAMAIS directement a un correspondant, il envoie toujours un projet a
|
|
Nabil qui decide et envoie lui-meme depuis OWA. Les Cas d'usage 1
|
|
(Trouver+envoyer), 3 (Ingestion AO), 4 (Veille reglementaire) et le bloc
|
|
REGLES COMPORTEMENTALES ont ete conserves, adaptes a la nouvelle API.
|
|
|
|
## Session expiree (code 409)
|
|
|
|
Si l'API renvoie **409**, la session du navigateur a expire. NE JAMAIS
|
|
tenter de re-authentifier depuis l'agent : signaler a Nabil qu'une
|
|
reconnexion manuelle via noVNC (port 8810, LAN) est necessaire.
|
|
|
|
## PIEGE — recreate / docker compose up -d du conteneur
|
|
|
|
Edge tue brutalement laisse des verrous perimes dans le volume persistant.
|
|
AVANT tout `docker compose up -d` / recreate de `hermes-mail-browser`,
|
|
TOUJOURS supprimer d'abord :
|
|
|
|
```
|
|
rm -f /volume1/docker/hermes-mail-browser/data/profile/SingletonLock \
|
|
/volume1/docker/hermes-mail-browser/data/profile/SingletonCookie \
|
|
/volume1/docker/hermes-mail-browser/data/profile/SingletonSocket
|
|
```
|
|
|
|
Incident deja rencontre et resolu deux fois — cause = verrous Singleton
|
|
perimes empechant Edge de redemarrer dans le profil persistant.
|
|
|
|
---
|
|
|
|
## Garde-fous /draft-reply (phase 2.1 — 2026-07-23)
|
|
|
|
Objectif : POST /draft-reply ne doit JAMAIS partir d'une initiative autonome
|
|
de hermes-tt (cron ou exces de zele), uniquement sur demande explicite de
|
|
Nabil dans le message en cours. Implemente dans `app/main.py`.
|
|
|
|
- **confirmed_by_user (obligatoire)** : le modele DraftReply exige
|
|
`confirmed_by_user: bool`. Absent ou `false` -> HTTP 400 (aucun envoi).
|
|
L'agent ne met `true` que si Nabil a explicitement demande la reponse.
|
|
- **Rate-limit (circuit-breaker)** : 5 envois reussis max par fenetre
|
|
glissante d'une heure. Au-dela -> HTTP 429. La fenetre est calculee depuis
|
|
le journal d'audit (source de verite persistante, survit aux redemarrages).
|
|
- **Journal d'audit persistant** : `/data/draft_reply_audit.log` (=
|
|
`/volume1/docker/hermes-mail-browser/data/draft_reply_audit.log`), 1 ligne
|
|
JSON par appel (accepte ou rejete) : timestamp ISO, subject, body_len,
|
|
confirmed_by_user recu, result (sent / rejected_no_confirmation /
|
|
rejected_rate_limit / error_*), original_index.
|
|
- **GET /draft-reply/audit?limit=N** : lecture seule des N derniers appels.
|
|
|
|
### Tests reussis (2026-07-23)
|
|
- POST sans confirmed_by_user -> **400** (message garde-fou), aucun envoi. OK
|
|
- POST confirmed_by_user=true -> **200**, mail projet recu dans la boite pro. OK
|
|
- 6 requetes confirmed_by_user=true en rafale -> req #1-5 **200**, req #6
|
|
**429** (rate-limit). OK
|
|
- GET /draft-reply/audit -> 7 entrees correctes (1 rejet-confirmation, 5
|
|
sent, 1 rejet-rate-limit). OK
|
|
- Journal de test archive en `draft_reply_audit.log.selftest-20260723` et
|
|
journal production remis a zero (budget rate-limit plein pour l'usage reel).
|
|
|
|
### Deploiement (methode prudente, sans recreate)
|
|
- `main.py` modifie sur l'hote, `ast.parse` OK, sauvegarde `main.py.bak-*`.
|
|
- `/app` n'est PAS bind-monte (seul `/data` l'est) -> `docker cp main.py`
|
|
dans le conteneur EN COURS, puis `docker restart hermes-mail-browser`.
|
|
- Le restart est sur : `start.sh` supprime deja les verrous
|
|
Singleton{Lock,Cookie,Socket} + /tmp/.X99-lock au demarrage (idempotent),
|
|
et Edge repart sur le profil persistant -> session O365 conservee
|
|
(`/auth/status` -> authenticated:true apres restart, verifie).
|
|
|
|
## Skills en contexte cron (verifie 2026-07-23, hermes_agent 0.17.0)
|
|
|
|
Question : un job cron avec `"skills": []` charge-t-il tous les skills de
|
|
`/opt/data/skills/` ou aucun ?
|
|
**Reponse : aucun skill n'est PRECHARGE dans le prompt du job.**
|
|
`cron/scheduler.py::_build_job_prompt` : quand la liste `skills` est vide,
|
|
`skill_names` est vide -> le prompt est assemble avec `has_skills=False`,
|
|
AUCUN contenu de skill n'est injecte. Le champ `skills` ne prend effet que
|
|
s'il liste explicitement des noms de skills a charger.
|
|
**Nuance importante** : l'agent cron tourne quand meme avec le TOOLSET
|
|
COMPLET par defaut (`_resolve_cron_enabled_toolsets` -> full set ; seuls
|
|
`cronjob`, `messaging`, `clarify` + `{moa,homeassistant,rl}` sont retires).
|
|
Le toolset `skills` reste disponible -> un agent cron pourrait, de sa propre
|
|
initiative, charger `mail-o365-tt` et joindre l'API. D'ou l'interet des
|
|
garde-fous techniques cote hermes-mail-browser (le skill seul ne suffit pas a
|
|
garantir qu'aucun appel autonome ne parte).
|