Files
hermes 39df85b51c fix: архивация/вложения больше не помечают письма прочитанными (Seen)
Причина: himalaya message read и attachment download используют IMAP BODY[],
который по RFC 3501 выставляет \Seen на сервере (Microsoft Exchange).
Пользователь: письма в ящике после скачивания становятся прочитанными.

Фикс:
- чтение тела: himalaya message read --preview (не ставит Seen)
- вложения: fetch_attachments_imaplib() — сырой IMAP stdlib (socket+ssl),
  UID FETCH (BODY.PEEK[]), папки в modified UTF-7, литералы до 1.5МБ,
  MIME-encoded words, фолбэк himalaya + flag remove seen

Проверено живьём: UID 14200 (INBOX, docx 1.1МБ) флаги ()->() — Seen не выставлен.
Openspec: change no-mark-seen-on-archive заархивирован (2026-09-14-no-mark-seen-on-archive), 7/7 validate OK
2026-09-14 08:08:48 +00:00

69 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# email-storage-format Specification
## Purpose
Формат хранения архива писем: `email.md` (YAML-frontmatter + текст) в структуре
`/<folder>/YYYY/MM/<uid>/`, выбранный по итогам анализа STORAGE_ANALYSIS.md
(9 критериев: полнота заголовков, инкрементальность, идемпотентность, удобство
поиска и др.). Хранит полные заголовки письма в frontmatter и тело как Markdown;
доп. поля (classification, handled_*, attachments) расширяют frontmatter без
изменения формата.
## Requirements
### Requirement: REQ-EMA-STORAGE-001: Обоснование выбора формата хранения
**MUST** — проект должен содержать документ `STORAGE_ANALYSIS.md` в корне
`/opt/hermes/email-assistant/`, объективно сравнивающий текущий формат
хранения (`email.md` в `/<folder>/YYYY/MM/UID/`) с Maildir, MBOX и notmuch.
#### Scenario: Документ анализа существует
**GIVEN** файл `STORAGE_ANALYSIS.md` существует
**WHEN** его открывают
**THEN** он содержит:
- таблицу сравнения по критериям (производительность, устойчивость, интеграция,
пригодность для LLM, совместимость с MUA, масштабируемость, бэкапы)
- явную рекомендацию (остаться на текущем / мигрировать на Maildir / иное)
- обоснование рекомендации с учётом мотивации пользователя (локальная LLM
в скриптах, без облака)
### Requirement: REQ-EMA-STORAGE-002: Ссылка из README
**MUST** — `README.md` проекта должен содержать ссылку на `STORAGE_ANALYSIS.md`.
#### Scenario: README содержит ссылку
**GIVEN** `README.md` проекта
**WHEN** открываем его
**THEN** в разделе «Оценка альтернатив» (или аналогичном) есть ссылка
`[Анализ формата хранения (ФС vs Maildir)](STORAGE_ANALYSIS.md)`.
### Requirement: REQ-EMA-STORAGE-003: Без изменения данных
**MUST** — change не должен модифицировать, мигрировать или удалять
существующие письма в `/opt/hermes/email/`. Анализ — только документация.
#### Scenario: Архив не изменён
**GIVEN** архив `/opt/hermes/email/`
**WHEN** change применён
**THEN** файлы писем остаются без изменений (проверка: `find /opt/hermes/email -name 'email.md' | wc -l` — то же число, что и до change).
### Requirement: Архивация не помечает письмо прочитанным
Чтение тела письма при архивации MUST NOT выставлять IMAP-флаг `\Seen`.
`mail_archive.py` для получения тела использует `himalaya message read` с
флагом `--preview` (документировано: читает БЕЗ установки `\Seen`).
#### Scenario: Архивация непрочитанного письма
- **GIVEN** письмо в INBOX с флагами `()` (непрочитанное)
- **WHEN** `mail_archive.py` архивирует письмо (пишет `email.md`)
- **THEN** в frontmatter `email.md` флаг `Seen` отсутствует И на IMAP флаги
письма остаются `()`
#### Scenario: Флаги в frontmatter соответствуют IMAP
- **GIVEN** письмо заархивировано после фикса
- **WHEN** флаги письма на IMAP меняются (пользователь прочитал/ответил)
- **THEN** frontmatter `email.md` после следующей синхронизации отражает флаги
IMAP (Seen появляется только если письмо реально прочитано пользователем)