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

171 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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-хэш поддерживает
любую длину имени