6.2 KiB
6.2 KiB
Контекст проекта — почтовый модуль
Веб-клиент почты + админка почтового сервера для внутренней платформы (~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)
- Реальные письма отображаются, отправка работает
Известные баги (следующие задачи)
- Sent пустой — smtp_sender.py не делает IMAP APPEND в папку Sent после отправки
- Черновики не сохраняются — при закрытии 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-уведомления