Session close 2026-09-15 (вечер): imap_stream Фаза 1 реализован, backlog urgent закрыт (фильтр актуальности), live-тесты OK

This commit is contained in:
2026-09-15 19:10:08 +00:00
parent 5a81c86599
commit 99e8e847f3
3 changed files with 105 additions and 2 deletions
+24
View File
@@ -157,6 +157,30 @@ Hermes cron:
- [x] **Репозиторий переведён на gitverse (источник истины)**: создан приватный `kpa39l/email-assistant` на gitverse.ru (id 336792) через API; remote `gitverse` добавлен; master запушен; **gitea: pull mirror `estorozhenko/email-assistant` ← gitverse (12h, id 54)** — gitea.nixg.ru остаётся зеркалом, не источником
- [x] **AGENT.md создан** — политика репозитория: gitverse = истина, gitea = зеркало, команды пуша, **местоположение токенов** (git-tokens.env, VESTI_BOT_TOKEN, TELEGRAM_CHAT_ID)
## Сделано в сессии 2026-09-15 (вечер) — imap_stream.py реализован + backlog urgent закрыт
### imap_stream.py — Фаза 1 (imap-realtime-sync, задачи 3–5) ✅
- [x] **`scripts/imap_stream.py` (новый, ~690 строк)** — постоянный IMAP IDLE-поток на сыром socket поверх `imap_client.imap_connect` (aioimaplib не ставится):
- IDLE-цикл: `idle_start` → `idle_wait(25с)` → `idle_done` → перевыпуск (Exchange рвёт IDLE ~60с, поэтому IDLE_TIMEOUT=25с)
- Reconnect с паузой `CONNECT_PAUSE=45с` (rate-limit Exchange), цикл переживает обрыв (проверено live: 150с демон → обрыв → reconnect → SELECT)
- `reconcile_new` — новые UID (архивация через mail_archive) + `reconcile_full` каждые 5 циклов (флаги/удаления)
- SQLite `/opt/hermes/email/state/mailbox.db`: `mailbox_state` (uid, folder, message_id, in_reply_to, refs, flags, has_attachment, archive_path, last_seen, deleted) + `mailbox_events`
- CLI: `--check`, `--test-idle`, `--status`, `--metrics`, без аргументов — демон
- [x] **Live-тесты Exchange (пауза ≥45с между коннектами) — все прошли**: `--check` (LOGIN 365 писем), `--test-idle` (SELECT → reconcile → IDLE 30с → 0 событий → DONE, EXIT=0), демон 150с (обрыв+reconnect)
- [x] **Исправлено live-тестами (питфолы, детали в WALKTHROUGH):** HERMES_REAL_HOME в imap_client (_load_credentials), `_cmd_ok` (хвост \r\n), колонка `references`→`refs` (SQLite), **UID-батчинг `1:1000` пуст** → `UID SEARCH ALL`/`UID <min>:*` (иначе все письма ложно deleted), Exchange не шлёт `+ idling` → `+ IDLE accepted`
- [x] **Запушено в gitverse**: `5a81c86` (imap_stream + фикс токена TG + фильтр актуальности + HERMES_REAL_HOME)
### Backlog urgent (10 писем) — закрыт ✅
- [x] **Корень найден**: `email_handlers.py` при наличии python-dotenv шёл в ветку `if load_dotenv` и НЕ грузил `/opt/vesti/.env` → `VESTI_BOT_TOKEN` пуст → все уведомления падали. Фикс: vesti/.env грузится всегда
- [x] **5 сентябрьских писем доставлены в ЛС** (msg_id 62–64 и далее), помечены handled_urgent
- [x] **Фильтр актуальности (запрос пользователя)**: `URGENT_MAX_AGE_DAYS=3` + `is_urgent_recent()` — письма старше 3 дней НЕ шлются в Telegram (помечаются handled_urgent); 5 старых (июль/авг) пропущены корректно
- [x] Идемпотентность сохранена: дубли предотвращены (14229 помечен вручную)
### Открыто на следующую сессию
- [ ] Запуск imap_stream.py как постоянного сервиса (systemd/cron) — код готов, не запущен навсегда
- [ ] Баг Radicale: `[task] PUT 400: Bad Request` (VTODO-задача, не относится к urgent) — не разобран
- [ ] Полный reconcile по всем подпапкам INBOX (сейчас Фаза 1 — только INBOX)
### Задача 1: Веб-интерфейс ассистента ⬜
- [ ] FastAPI + SQLite FTS5: список писем (дата/адресант/тэги/папка)
- [ ] Перемещение в папку; тэги