Причина: 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
4.2 KiB
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 появляется только если письмо реально прочитано пользователем)