Files
email-assistant/openspec/specs/email-storage-format/spec.md
T
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

4.2 KiB
Raw Blame History

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