Files
email-assistant/openspec/changes/archive/2026-09-14-no-mark-seen-on-archive/tasks.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

2.3 KiB

Tasks: не помечать письма прочитанными при архивации

Задачи

  • 1. mail_archive.py, get_email_content(): добавлен --preview в вызов himalaya message read — флаг НЕ выставляет \Seen. Проверено: himalaya message read --preview (не ставит Seen).
  • 2. mail_archive.py, get_attachments(): himalaya attachment download НЕ имеет флага против Seen. Вместо него — новый путь: fetch_attachments_imaplib() — сырой IMAP (socket+ssl, stdlib) c UID FETCH ... (BODY.PEEK[]) — не выставляет \Seen. Используется с фолбэком на himalaya + flag remove seen (страховка).
  • 3. _imap_utf7_encode() — конвертация имени папки в IMAP modified UTF-7 (кириллица в имени папки на Exchange иначе не находится).
  • 4. Парсинг литерала {N} в ответе UID FETCH: чтение чанками по 64 КБ, ожидание полного литерала (письма до ~1.5 МБ).
  • 5. MIME-encoded word в get_filename(): декодирование через email.header.decode_header (например =?koi8-r?B?...?=).
  • 6. Живая проверка на реальном письме (UID 14200, INBOX, непрочитанное, вложение «Переместить стол.docx» 1.1 МБ): флаги до '' = после '' — \Seen НЕ выставлен, файл скачан.

Верификация (живой тест)

  • Письмо: UID 14200, папка INBOX, флаги до: () (непрочитанное).
  • fetch_attachments_imaplib("14200", "INBOX", dest) → True, 1 вложение: «Переместить стол.docx» (1 117 244 байт).
  • Флаги после: () — без \Seen.
  • Ранее: UID 320 (непрочитанное, без вложений): BODY.PEEK[] не меняет флаги.
  • Письмо 52 (INBOX/Организация работы, кириллица в имени папки): 4 docx-вложения скачаны через mUTF-7-папку, флаги не тронуты.