# Контекст проекта — почтовый модуль Веб-клиент почты + админка почтового сервера для внутренней платформы (~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" deeily@10.101.10.223:` ## Ключевые файлы ``` 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/, ?uid=, ?filter= app/blueprints/api/ — AJAX: /api/mail//*, /api/mail/bulk/*, /api/mail/send, /api/stream/ 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-уведомления