84 lines
6.2 KiB
Markdown
84 lines
6.2 KiB
Markdown
# Контекст проекта — почтовый модуль
|
||
|
||
Веб-клиент почты + админка почтового сервера для внутренней платформы (~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 (240–800px), 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: новые письма появляются без перезагрузки страницы
|
||
|
||
### Инфраструктура (Фазы 1–3 — 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-уведомления
|