# 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) ```python 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-хэш поддерживает любую длину имени