| От {{ sortArrow('sender_name') }} | Тема {{ sortArrow('subject') }} | Кому {{ sortArrow('sender_email') }} | Получено {{ sortArrow('received_at') }} | Отправлено {{ sortArrow('sent_at') }} | 📎 | Размер {{ sortArrow('size') }} |
|---|---|---|---|---|---|---|
| {{ m.sender_name || m.sender_email || '—' }} | {{ m.subject || '(без темы)' }} — {{ m.preview }} · {{ m.folder }} | {{ m.to_repr || '—' }} | {{ fmtDate(m.received_at) }} | {{ fmtDate(m.sent_at) }} | {{ m.has_attachments ? '📎' : '' }} | {{ fmtSize(m.mime_size_bytes) }} |
| {{ t.last?.sender_name || t.last?.sender_email || '—' }} | {{ t.any_subject || '(без темы)' }} {{ t.cnt }} — {{ t.last.preview }} | {{ t.last?.to_repr || '—' }} | {{ fmtDate(t.last_at) }} | {{ t.has_att ? '📎' : '' }} | ||
| {{ m.sender_name || m.sender_email || '—' }} | {{ m.preview }} | {{ m.to_repr || '—' }} | {{ fmtDate(m.received_at) }} | {{ m.has_attachments ? '📎' : '' }} |
{{ selected.subject || '(без темы)' }}
Вложения ({{ selected.attachments.length }})
📎 {{ a.filename }} · {{ fmtSize(a.size_bytes) }}Цепочка ({{ selected.thread_siblings.length }})
📊 Статистика
Активность
Топ-10 отправителей
| {{ s.name || s.email }} | {{ s.email }} | {{ s.n }} |
Активность — часы × дни недели
Забытые треды — >7 дней без ответа
| {{ f.subject || '(без темы)' }} | {{ f.sender_name || f.sender_email }} | {{ fmtDate(f.received_at) }} |
Скорость ответов
По папкам
| {{ folderLabel(f.folder) }} | {{ f.n }} |
⚙️ Настройки
Подключение к Exchange
Расписание синхронизации
Экспорт архива
Тема оформления
Смена пароля
Состояние сервиса
| Писем в архиве | {{ statusInfo.overall.total || 0 }} |
| Самое старое письмо | {{ fmtFullDate(statusInfo.overall.first) }} |
| Самое новое письмо | {{ fmtFullDate(statusInfo.overall.last) }} |
| Архив писем (.eml) | {{ fmtSize(statusInfo.disk.mime_bytes) }} · {{ statusInfo.attachments.n || 0 }} вложений уже внутри (единый источник) |
| Свободно на диске | {{ fmtSize(statusInfo.disk.free_bytes) }} из {{ fmtSize(statusInfo.disk.total_bytes) }} |
Синхронизация по папкам
| {{ folderLabel(c.folder) }} | последнее письмо: {{ fmtFullDate(c.last_received_at) }} · проверено: {{ fmtRelative(c.last_fetched_at) }} |
Последние синхронизации
| {{ fmtFullDate(r.started_at) }} | {{ folderLabel(r.folder) }}: +{{ r.added }}{{ r.errors ? `, ошибок: ${r.errors}` : '' }} |
❓ Справка
Что это за сервис
MAIL RMG — личный архив корпоративной Exchange-почты. Работодатель удаляет письма старше 3 месяцев, а сервис ежечасно забирает свежие и хранит их вечно у тебя на сервере с удобным поиском. Работает в одну сторону: письма приходят из Exchange в архив, обратно ничего не пишется.
📬 Раздел «Почта»
| Sidebar → папки | Входящие / Отправленные / Черновики + пользовательские папки из Exchange. «Всё» — без фильтра. |
| Плоский список / Треды | Плоский — все письма по дате. Треды — сгруппированные переписки (клик по треду раскрывает все ответы). |
| ☰ Широкий вид | Карточки с превью первых строк — как в Gmail. Выбор сортировки через dropdown. |
| ≡ Компактный вид | Табличный, как в Outlook. Сортировка по клику на заголовок колонки (↑ / ↓). |
| ПКМ по письму | Контекстное меню: открыть, скачать .eml, удалить. |
| В открытом письме | ← пред. / след. → — навигация, .eml — скачать оригинал, HTML / текст — переключить рендер, 📋 Заголовки — полные заголовки (From, Received, DKIM…), 🗑 Удалить — удалить письмо. |
| HTML vs текст | По умолчанию HTML (если есть). Рендерится в изолированном iframe sandbox — внешние картинки и трекинг-пиксели не грузятся. |
| Вложения | Показываются внизу письма плитками. Клик — скачивание. Файлы не дублируются на диске: достаются на лету из .eml. |
🔍 Поиск и операторы
Поиск понимает русскую морфологию — «встреча» найдёт «встречи», «встречу». Работает одинаково по теме, отправителю и телу письма. Результаты ранжируются по релевантности.
Операторы можно комбинировать:
from:иванов | письма от — совпадение с именем или email |
to:petrov@rr.ru | письма кому-то конкретному (To/CC/BCC) |
has:attachment | только с вложениями |
in:inbox | ограничить папкой (inbox / sent / drafts / имя пользовательской) |
older:30d | старше N дней (d/w/m/y) или чем дата ISO older:2026-01-01 |
newer:7d | новее N дней или ISO-даты |
subject:договор | слово только в теме письма |
| пример | from:грибачёва has:attachment newer:14d — от Грибачёвой, с вложением, за последние 14 дней |
Кнопка ? рядом со строкой поиска всегда под рукой — откроет ту же шпаргалку.
⌨️ Горячие клавиши
/ | фокус в поиск |
j / k | следующее / предыдущее письмо в списке |
Enter | открыть первое |
← / → | пред. / след. в открытом письме |
Esc | закрыть письмо, меню или модалку |
Delete | удалить открытое письмо (с подтверждением) |
📊 Статистика
| Карточки сверху | Всего писем · За 7 / 30 / 365 дней · Объём архива |
| График активности | 30/90/365 дней. Линии: входящие, отправленные. Период > 90 дней — группировка по неделям. |
| Топ отправителей | 10 человек с наибольшим числом писем в Inbox. |
| Heatmap | Интенсивность писем по часам × дням недели. Чем темнее ячейка — тем больше писем. |
| Забытые треды | Письма входящие старше 7 дней, на которые ты не отвечал. Клик — открыть. |
| Скорость ответа | Медианное время между входящим и моим ответом в том же треде. |
⚙️ Настройки
| Подключение к Exchange | Email, пароль, EWS-сервер. Эти данные можно менять в любой момент — при сохранении архив продолжит расти из той учётки которая введена. Пароль передаётся только если его заполнить (пустое поле = не менять). |
| Расписание синхронизации | Как часто дёргать Exchange. «Каждый час» (default) — баланс между свежестью и нагрузкой. «Будни только» / «Ночная пауза» — чтобы не долбить Exchange ночью и на выходных. |
| ⚡ Синхронизировать сейчас | Ручной pull — игнорирует расписание. Во время работы в шапке видна полоса прогресса с current/total. |
| Экспорт архива | ZIP с EML-файлами по папкам + manifest.json. Фильтр по датам и папке. Открывается в Outlook / Thunderbird двойным кликом. |
| Тема | Авто (следует системной) / Тёмная / Светлая. Выбор сохраняется в браузере. |
| Смена пароля | Текущий пароль нужно ввести для подтверждения. Новый минимум 6 символов. |
| Состояние сервиса | Сколько писем, объём архива, свободно на диске, когда был последний pull. |
💾 Где и как хранятся письма
Единственная копия. Каждое письмо лежит в виде оригинального .eml в /srv/mailrr/data/mime/YYYY/MM/. Это RFC822-формат, открывается в Outlook/Thunderbird двойным кликом.
Метаданные + индексы поиска — в PostgreSQL (база mailrr). БД можно полностью пересобрать из .eml-файлов если что-то сломается.
Вложения не дублируются на диске. Раньше лежали отдельной папкой, теперь извлекаются из .eml на лету — экономит ~2 GB. При клике по вложению задержка 50–200 мс — незаметно.
Бэкапы в /root/backups/mailrr/ — только pg_dump метаданных и снимок кода. Письма не дублируются в бэкапе (места занимают слишком много, смысла мало). Если нужна защита от падения диска — подключить внешний sync (R2/Я.Диск).
🧪 Как проверить здоровье сервиса
Публичный endpoint без авторизации:
curl https://mailrr.vborisoff.ru/api/health
→ {"ok":true,"messages":5228,"last_fetch":"2026-04-24T..."}
Подключи к UptimeRobot / Healthchecks.io чтобы получать уведомления если сервис ляжет.
🚀 Перенос на другой сервер
В /root/backups/mailrr/ лежит mailrr-service-*.tar.gz (~58 KB) — весь код сервиса без данных. Внутри архива — README.md с пошаговой инструкцией развёртывания: создать БД, распаковать, поставить venv, настроить systemd+nginx+certbot, войти в UI и ввести свои Exchange-креды в setup wizard.
Удобно отдавать коллегам: сервис универсальный, каждый вводит свои данные Exchange → свой архив начинает расти.
⚠ Ограничения
- Если Microsoft отключит Basic Auth на EWS — сервис перестанет забирать почту. Придётся переходить на OAuth2 через Microsoft Graph (нужна регистрация приложения в Azure AD).
- Удалённое письмо — безвозвратно. Восстановить нельзя ни из архива, ни из Exchange (если оно там уже пропало).
- Архив хранится только на одном диске. Если диск умрёт — потеряется всё. Для защиты подключить внешний sync.
- Вложения больше 14 MB встречаются редко, но при скачивании может быть небольшая задержка (парсинг .eml).