Files
email-assistant/openspec/changes/email-classification-handlers/tasks.md
T
hermes 7550aff102 feat: классификация писем Qwen3:8b + обработчики (urgent→TG, task→VTODO, meeting→VEVENT)
- mail_archive.py: фикс вложений himalaya --dir → --downloads-dir; attachments/ только при has_attachment; идемпотентно
- email_classifier.py: Qwen3:8b (Ollama) → теги info/urgent/task/meeting в frontmatter email.md
- email_handlers.py: urgent→Telegram (Bot API+SOCKS5), task→Radicale VTODO, meeting→Radicale VEVENT; handled_* идемпотентность; --dry-run
- .gitignore: игнор *.env.bak*
- openspec: чейндж email-classification-handlers (в работе)
- STATUS/TODO/WALKTHROUGH: прогресс сессии, подводные камни Radicale (http.client, Depth:1, формат дат)
2026-09-13 20:35:58 +00:00

4.2 KiB

Tasks: Классификация писем и подключение обработчиков

1. Починить скачивание вложений

  • 1.1 Исправить get_attachments() в scripts/mail_archive.py: заменить --dir на --downloads-dir, передавать <msg_dir>/attachments/
  • 1.2 Не создавать папку attachments/ для писем без вложений (создавать только если has_attachment: true или команда что-то вернула)
  • 1.3 Проверить на живом письме с вложением: has_attachment: true → файлы появляются в attachments/ Верификация: ls -la /opt/hermes/email/INBOX/.../<uid>/attachments/
  • 1.4 Проверить идемпотентность: повторный запуск не качает повторно

2. Классификатор писем (email_classifier.py)

  • 2.1 Создать scripts/email_classifier.py: - читает неклассифицированные email.md (нет classification) - чистит текст (переиспользовать clean_body из contacts_extractor) - вызывает Qwen3:8b (Ollama localhost:11434) с промптом классификации - получает JSON: tags + reason + (для meeting) datetime
  • 2.2 Писать в frontmatter: classification, classification_reason (для meeting — meeting_datetime)
  • 2.3 Обработка ошибок: невалидный JSON/нет ответа → unclassified, продолжить
  • 2.4 --limit N для дозирования (как contacts_extractor)
  • 2.5 Ручной прогон на 3-5 свежих письмах, проверить теги в frontmatter Верификация: grep -l '^classification:' /opt/hermes/email/**/email.md | head

3. Обработчики (email_handlers.py)

  • 3.1 Создать scripts/email_handlers.py: сканирует письма с тегами и без handled_*
  • 3.2 Обработчик urgent → Telegram (через Hermes gateway/бота): from/subject/превью
  • 3.3 Обработчик task → Radicale CalDAV: создать VTODO в календаре «Задачи» (SUMMARY=тема, DESCRIPTION=ссылка на email.md, DTSTART/DUE при наличии даты) вместо Vikunja API (см. чейндж remove-vikunja-use-radicale-tasks)
  • 3.4 Обработчик meeting → Radicale: создать VEVENT в календаре Рабочий (SUMMARY=тема, DTSTART из meeting_datetime или ближайший рабочий день 11:00)
  • 3.5 Помечать письмо handled_urgent / handled_task / handled_meeting
  • 3.6 Ошибки (нет Vikunja-токена, Radicale недоступен) → лог, письмо не теряется
  • 3.7 Проверить: urgent-письмо уходит в Telegram; meeting-письмо создаёт VEVENT

4. Подготовка зависимостей

  • 4.1 Секреты в .env/config: Telegram chat_id/token (для обработчика urgent), Radicale Basic-auth (уже есть в проекте)
  • 4.2 Убедиться, что календарь «Задачи» Radicale существует и доступен Верификация: curl -u estorozhenko:... -X PROPFIND -H 'Depth: 0' https://cal.nixg.ru/estorozhenko/<urlencoded Задачи>/

5. Cron

  • 5.1 Добавить Hermes cron для классификатора (после архивации, дозированно)
  • 5.2 Добавить Hermes cron для обработчиков
  • 5.3 Проверить, что цепочка работает end-to-end на новом письме (архивация → классификация → обработчик)

6. Документация

  • 6.1 Обновить STATUS.md: новые скрипты, cron, фронтмэттер поля
  • 6.2 Зафиксировать доступы (Vikunja token, Telegram) в ресурсах проекта