Files
email-local-archive/references/dynamic-folder-discovery.md
2026-09-06 13:51:14 +00:00

7.6 KiB
Raw Permalink Blame History

Dynamic Folder Discovery — решение для хардкода INBOX_SUBFOLDERS

Контекст

mail_archive.py содержит захардкоженный INBOX_SUBFOLDERS (18 папок). На IMAP-сервере реально 137 подпапок INBOX, включая многоуровневые.

Текущее состояние

State-файлы (следы прошлых запусков)

/opt/hermes/email/state/
├── mail-archive-last-Archive.json
├── mail-archive-last-INBOX.json
├── mail-archive-last-INBOX_!Scan.json
├── mail-archive-last-Sent.json
├── mail-archive-last-folder_41a7755da018.json   # хэш от не-ASCII имени
├── mail-archive-last-folder_5dd417336b45.json
├── mail-archive-last-folder_6dfd3661f092.json
├── mail-archive-last-folder_a2d2b831a004.json
├── mail-archive-last-folder_a59f0da18423.json
├── mail-archive-last-folder_b002f4b75367.json
├── mail-archive-last-folder_b8338b886347.json
├── mail-archive-last-folder_ba130b3adfda.json
├── mail-archive-last-folder_e5dd3de630eb.json

State-файлы уже поддерживают произвольные имена папок (через get_state_file() — MD5-хэш для не-ASCII). Инфраструктура готова.

Хардкод в mail_archive.py (строки 54-73)

INBOX_SUBFOLDERS = [
    "INBOX/!Scan",
    "INBOX/!Битрикс",
    "INBOX/!ВГ Чек листы",
    "INBOX/!Документооборот",
    "INBOX/!Завки",
    "INBOX/!Материалы",
    "INBOX/!Отчеты",
    "INBOX/!Персонал",
    "INBOX/!Протоколы",
    "INBOX/!Реестр оплаты",
    "INBOX/!Торик",
    "INBOX/Бюджет",
    "INBOX/Контрагенты",
    "INBOX/ЛНД",
    "INBOX/Организация работы",
    "INBOX/Приемка и стройка",
    "INBOX/Системы",
    "INBOX/Эксплуатация",
]

Реальные папки на сервере (137 шт.)

Полный список получен через himalaya folder list:

INBOX/!Scan
INBOX/!Битрикс
INBOX/!ВГ Чек листы
INBOX/!Документооборот
INBOX/!Завки
INBOX/!Материалы
INBOX/!Отчеты
INBOX/!Персонал
INBOX/!Персонал/ОТ и ТБ
INBOX/!Протоколы
INBOX/!Реестр оплаты
INBOX/!Реестр оплаты/Акты
INBOX/!Реестр оплаты/Закупки
INBOX/!Реестр оплаты/Закупки/10 рабочих мест
INBOX/!Реестр оплаты/Закупки/NanoCad
INBOX/!Реестр оплаты/Закупки/Горизонт Ноутбуки
INBOX/!Реестр оплаты/Закупки/Дооснащение ТГ
INBOX/!Реестр оплаты/Закупки/Касперский для ВГ
INBOX/!Реестр оплаты/Закупки/Модернизация Wi-Fi
INBOX/!Реестр оплаты/Закупки/Оборудование горизонт
INBOX/!Реестр оплаты/Закупки/Сервер
INBOX/!Реестр оплаты/Закупки/Цветной МФУ ТГ
INBOX/!Торик
INBOX/Бюджет
INBOX/Бюджет/Винный город
INBOX/Бюджет/Винный город/CAPEX 2025
INBOX/Бюджет/Винный город/Capex 2026
INBOX/Бюджет/Винный город/OPEX 2025
INBOX/Бюджет/Винный город/OPEX 2026
INBOX/Бюджет/Винный город/OPEX 2027
INBOX/Бюджет/Горизонт
INBOX/Бюджет/Горизонт/CAPEX 2025
INBOX/Бюджет/Горизонт/CAPEX 2026
INBOX/Бюджет/Горизонт/OPEX 2026
INBOX/Бюджет/Тихая гавань
INBOX/Бюджет/Тихая гавань/CAPEX 2025
INBOX/Бюджет/Тихая гавань/CAPEX 2026
INBOX/Бюджет/Тихая гавань/OPEX 2025
INBOX/Бюджет/Тихая гавань/OPEX 2026
INBOX/Контрагенты
INBOX/Контрагенты/iiko
INBOX/Контрагенты/iiko/Тихая гавань
INBOX/Контрагенты/АБ-Транзит
INBOX/Контрагенты/Аврора
INBOX/Контрагенты/Ассистент
INBOX/Контрагенты/Билайн
INBOX/Контрагенты/Интеллект - ilocks - замки
INBOX/Контрагенты/Интертех Лицензии Huawei
INBOX/Контрагенты/Квадротек
INBOX/Контрагенты/Кит
INBOX/Контрагенты/Компания АйТи
INBOX/Контрагенты/Кристалл
INBOX/Контрагенты/Крым-Строй-Сервис
INBOX/Контрагенты/Лимон
INBOX/Контрагенты/Медиа-Сервис
INBOX/Контрагенты/МеталлПрофиль
INBOX/Контрагенты/Ново-групп
INBOX/Контрагенты/Орт-Сервис
INBOX/Контрагенты/Партнер
INBOX/Контрагенты/Партнеры
INBOX/Контрагенты/Пиксель
INBOX/Контрагенты/Поставщики
INBOX/Контрагенты/Рубикон-С
INBOX/Контрагенты/СБСС
INBOX/Контрагенты/Самоваръ
INBOX/Контрагенты/Сервисный центр
INBOX/Контрагенты/Смарт
INBOX/Контрагенты/СпецТехМонтаж
INBOX/Контрагенты/Стрим
INBOX/Контрагенты/СтройПартнер
INBOX/Контрагенты/ТД ТрансМет
INBOX/Контрагенты/ТД Лайт
INBOX/Контрагенты/Технологии Доверия
INBOX/Контрагенты/Технополис
INBOX/Контрагенты/Типография
INBOX/Контрагенты/УралТрансПром
INBOX/Контрагенты/Физ лица
INBOX/Контрагенты/Цифровые решения
INBOX/Контрагенты/ЭнергоСпецКомплект
INBOX/Контрагенты/Энергия
INBOX/Контрагенты/Югспецодежда
INBOX/ЛНД
INBOX/Организация работы
INBOX/Приемка и стройка
INBOX/Системы
INBOX/Эксплуатация

План исправления

  1. В mail_archive.py заменить INBOX_SUBFOLDERS на функцию get_all_folders():

    • himalaya folder list --output json
    • Фильтр: папки, начинающиеся с INBOX/ (исключить Trash, Drafts, RSS, Archives)
    • Исключить INBOX (корневую — она уже в FOLDERS)
  2. --all должен использовать FOLDERS + get_all_inbox_subfolders() вместо FOLDERS + INBOX_SUBFOLDERS

  3. mail-archive-every-5min cron автоматически получит новые папки без изменения конфигурации

  4. State-файлы уже готовы — get_state_file() работает с любыми именами папок

Edge cases

  • Папки могут исчезнуть между запусками — archive_folder() уже обрабатывает No such folder через get_envelopes() (возвращает [])
  • Новая папка без писем — get_envelopes() вернёт пустой список, state не создаётся
  • Папки с \HasNoChildren и \HasChildren — himalaya folder list показывает все (независимо от флагов), так что фильтр по \HasNoChildren не нужен
  • Очень глубокие папки (3-4 уровня) — get_state_file() через MD5-хэш поддерживает любую длину имени