mail/CLAUDE.md
deeily 5024bf9a8d init: full mail stack — phases 0..8 (web client, admin, IMAP/SMTP,
sieve, search, sessions, dramatiq, deploy/install, ELK, monitoring)
2026-04-29 16:30:43 +03:00

84 lines
6.2 KiB
Markdown
Raw Permalink 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.

# Контекст проекта — почтовый модуль
Веб-клиент почты + админка почтового сервера для внутренней платформы (~300 пользователей). Встраивается через iframe. Самописный аналог Nextcloud/Bitrix. Отдельный репо, не git-инициализирован.
## Стек
- **Flask 3 + Python 3.13** (SSR Jinja2, blueprints), pip + requirements.txt
- **docker-mailserver v14** (Postfix + Dovecot + Rspamd) — источник правды для почты
- **PostgreSQL + Redis + Meilisearch + Dramatiq** (docker-compose)
- **IMAPClient** — IMAP, **smtplib** — SMTP submission port 587
- **UI:** web_template/ стиль (Notion-like, 0.5px borders, inline SVG, 13px, CSS vars, без фреймворков)
- **Nginx Proxy Manager** на хосте, Let's Encrypt, домены koreana.link / koreana.rest
## Сервер разработки
- `10.101.10.223` (Debian 13), пользователь `deeily`, SSH-ключ `~/.ssh/mail_deploy`
- Приложение: `/home/deeily/mail/`, venv: `.venv/`, запуск: `nohup .venv/bin/python wsgi.py >/tmp/flask.log 2>&1 &`
- Конфиг: `/home/deeily/mail/.env` (USE_MOCK_MAIL=0, IMAP_PASSWORD=admin123, SEND_DEFER_SECONDS=10)
- Docker: `cd ~/mail/docker && docker compose up -d`
- DMS hostname: `smtp.mail.local`, аккаунты: admin/admin123, user1/user123, user2/user123
- Деплой: `rsync -az -e "ssh -i ~/.ssh/mail_deploy" <src> deeily@10.101.10.223:<dst>`
## Ключевые файлы
```
app/__init__.py — Flask factory, context_processor inject_nav
app/config.py — Config class, USE_MOCK_MAIL, IMAP_*, SMTP_*, SEND_DEFER_SECONDS
app/services/mock_mail.py — in-memory mock (USE_MOCK_MAIL=1), источник групп/правил/подписей/shared
app/services/imap_client.py — реальный IMAP (IMAPClient), list_threads/get_message/move/flags/bulk
app/services/smtp_sender.py — реальный SMTP (smtplib port 587)
app/services/mail_service.py — адаптер mock↔real, единый API для blueprints
app/services/imap_idle.py — IMAP IDLE manager, push через SSE
app/services/md.py — markdown→sanitized HTML (bleach)
app/blueprints/mail/ — routes: /f/<folder_key>, ?uid=, ?filter=
app/blueprints/api/ — AJAX: /api/mail/<uid>/*, /api/mail/bulk/*, /api/mail/send, /api/stream/<folder>
app/blueprints/rules/ — CRUD правил
app/blueprints/settings/ — подписи + автоответчик
app/blueprints/shared/ — общие ящики (user + admin)
app/blueprints/groups/ — группы рассылок
app/templates/layout/base.html — sidebar + topbar + compose modal include
app/templates/mail/_compose_modal.html
app/templates/mail/folder.html — 3-колонка: список треддов + просмотр письма
app/static/app.js — весь JS (event delegation, chips, MD toolbar, send toast, SSE)
app/static/styles.css — весь CSS
docker/docker-compose.yml — postgres+redis+meili+mailserver
docker/dms-config/ — postfix-accounts.cf, postfix-main.cf (mydestination override)
```
## Что реализовано (UI mock + реальный IMAP)
### UI (Фаза 0b — done)
- Sidebar: кнопка «Написать», системные + пользовательские папки, общие ящики, Организация, Админка; collapse 196↔44px, localStorage
- Список писем: resizable (240800px), select-all, прочитать-все, фильтр (все/непрочитанные/с флажком/с вложениями), группировка в треды по нормализованной теме, bulk-toolbar
- Просмотр письма: звёздочка, важное, ответить/переслать/спам/переместить/удалить
- Compose modal: chips To/Cc/Bcc, выбор «От», MD-toolbar (B/I/S/H/quote/code/ul/ol/link/hr/preview), подписи с live-preview, важное, развернуть
- Send toast: 10 сек таймер, синяя полоска снизу карточки, кнопка отмены — реальный POST только после таймера
- IMAP IDLE + SSE: новые письма появляются без перезагрузки страницы
### Инфраструктура (Фазы 13 — done)
- DMS v14 запущен, IMAP/SMTP работают
- Flask переключён на реальный IMAP (USE_MOCK_MAIL=0)
- Реальные письма отображаются, отправка работает
## Известные баги (следующие задачи)
1. **Sent пустой** — smtp_sender.py не делает IMAP APPEND в папку Sent после отправки
2. **Черновики не сохраняются** — при закрытии compose без отправки письмо теряется
## Фазы (что впереди)
- **Фаза 4:** IMAP APPEND в Sent + автосейв черновиков в IMAP Drafts
- **Фаза 5:** Админка сервера (dms_config.py, домены/ящики/алиасы/DKIM)
- **Фаза 6:** Alembic миграции + Sieve-правила + Meilisearch поиск
- **Фаза 7:** Auth (Dovecot SASL логин, сессии в PG, app-passwords)
- **Фаза 8:** Прод (ACME, открытые порты, NPM, бэкап, мониторинг)
## Правила работы
- Стиль UI строго по web_template: без Bootstrap/Tailwind, inline SVG, 0.5px borders
- Деплой всегда через rsync на 10.101.10.223, Flask подхватывает изменения автоматически (debug mode)
- Группы/правила/подписи/shared mailboxes пока в памяти (mock_mail.py), в Фазе 6 переедут в Postgres
- IMAP = источник правды, Flask только читает/пишет через IMAPClient
- Не добавлять alert() — использовать toast-уведомления