MailCatch — высокопроизводительный автономный Catch-All почтовый сервер, парсер OTP-кодов и ссылок активации, а также движок массовых email-рассылок с автоматическим прогревом доменов (Warmup Engine) и встроенным AI-ассистентом на базе Python (FastAPI + aiosmtpd + SQLite WAL).
- Catch-All для неограниченного числа ящиков: сервер принимает входящие письма на любые адреса (
*@yourdomain.com). - Защита от Open Relay: строгая проверка доменов назначения (
550 5.7.1 Relaying denied). - Anti-Spoofing защита: блокировка внешних попыток подделки локальных адресов отправителя.
- Ограничение DoS: лимит размера входящего письма (до 10 МБ).
- Многоуровневое распознавание кодов (OTP / PIN / Verification Code): точный поиск 4–8 значных кодов подтверждения.
- Фильтрация ложных срабатываний: игнорирование номеров портов (
8080,3000), годов (1900-2099) и монотонных цифр (00000). - Поиск ссылок действий: автоматическое определение ссылок подтверждения аккаунта, верификации и сброса пароля (с фильтрацией ссылок отписки и соглашений).
- Интеллектуальный Warmup: плавное автоматическое увеличение скорости отправки по часам/дням для защиты репутации домена.
- Human-like Delay Jitter: добавление случайной задержки между письмами для имитации естественной отправки.
- Очередь повторных попыток (Retry Queue): классификация ошибок (4xx temporary vs 5xx permanent) с длинным экспоненциальным backoff (15 мин / 1 ч / 4 ч) — крупные шлюзы (Mimecast, Google, Microsoft) успевают снять троттлинг между попытками.
- Распознавание «фактически постоянных» 4xx: Cloudflare 452 suppression и стабильные 454 Relay access denied не повторяются по 3 раза.
- Шаблонизация: подстановка тегов
{{EMAIL}},{{NAME}},{{HOOK}}и{{UNSUB_URL}}в текст и тему письма.
- Прямая доставка по MX: автоматический поиск MX-серверов получателя с поддержкой RFC 5321 Fallback на A-записи.
- Принудительный IPv4: исключение проблем с доставкой из-за неаутентифицированных IPv6-маршрутов.
- Автоматическая DKIM RSA-2048 подпись: подписание исходящих писем приватным ключом, канонизация
relaxed/relaxed(устойчива к нормализации писем промежуточными шлюзами). - Шифрование Opportunistic TLS (STARTTLS): сначала попытка с верификацией сертификата, при его проблемах — повтор без верификации, в крайнем случае — plaintext (статус транспорта логируется по каждому письму).
- Трекинг открытий: генерация невидимого пикселя
1x1(/t/{token}.png). - RFC 8058 One-Click Unsubscribe: заголовки
List-UnsubscribeиList-Unsubscribe-Postдля Gmail / Yahoo (ровно по одному на письмо). Ссылка в теле ведёт на страницу подтверждения: сама отписка выполняется только по кнопке/POST — префетчеры корпоративных сканеров ссылок не могут отписать получателя за него. Отписка действует глобально на все кампании. - Защита от инъекций в заголовки: тема/адреса/кастомные заголовки очищаются от CR/LF, не-ASCII темы кодируются по RFC 2047.
- DNS-предпроверка при старте рассылки: фоновая проверка доменов получателей — исключаются только мёртвые домены (NXDOMAIN/NoNameservers); домены без MX, но с A-записью остаются отправителю (RFC 5321 §5.1 fallback).
- Автоподавление жёстких отскоков: только отказы уровня получателя (5xx на RCPT, мёртвый домен) попадают в глобальный стоп-лист; сбои уровня отправителя (блоклисты, отказ в MAIL FROM, контент-фильтры) адрес не подавляют. Асинхронные NDN-баунсы, пришедшие на catch-all, тоже гасят адрес.
- Краезащитная отправка без дублей: атомарный «клейм» получателя (
sending) исключает двойную отправку при нескольких воркерах; зависшие после краха записи возвращаются в очередь при старте. - A/B-тестирование тем и текста: детерминированное деление аудитории и автоматический выбор победителя по open rate.
- Классификация входящих ответов: интерес / вопрос / отказ / отписка / баунс / прочее, с уверенностью и кратким резюме.
- Авто-отписка по CAN-SPAM: запросы отписки обрабатываются мгновенно, адрес попадает в стоп-лист. При уверенности модели ниже 0.8 запрос сохраняется для ручного подтверждения, а не гасится автоматически.
- Обработка NDN-баунсов: асинхронные отчёты о недоставке подавляют адрес-получателя (только из собственных кампаний — защита от поддельных NDN).
- Черновики ответов лидам: сдержанный B2B-тон, язык ответа = язык входящего письма, отправка в один клик.
- QA-гейт шаблонов: проверка письма на спам-триггеры, CAN-SPAM (почтовый адрес, отписка) и качество темы перед запуском.
- Персонализация
{{HOOK}}: AI-обогащение доменов получателей (краткая персональная подводка на основе сайта компании).
- Шаблоны писем: сохранение, повторное использование, счётчик использований, адаптивный предпросмотр Desktop/Mobile с подстановкой тегов.
- Базы контактов: сохранение списков получателей, повторное использование в новых рассылках, экспорт в TXT.
- Стоп-лист: отписки, жёсткие отскоки и вручную исключённые адреса — автоматически вычитаются из любых новых рассылок.
- Современная темная панель управления (HTML5, CSS3, Jinja2, Vanilla JS).
- Поддержка авторизации через HTTP Basic Auth и API Key (
X-API-Keyили?api_key=...). - Встроенный Swagger UI (
/docs) и ReDoc (/redoc) с возможностью работы в изолированной сети (offline assets). - Защита от брутфорса паролей и API-ключей (Rate Limiter с блокировкой IP).
mailcatch/
├── main.py # Точка входа (SMTP + FastAPI + фоновые воркеры)
├── mailcatch/
│ ├── web.py # FastAPI веб-сервер, REST API и веб-панель
│ ├── smtp.py # SMTP Catch-All сервер (aiosmtpd)
│ ├── parser.py # Парсер MIME-сообщений, извлечение OTP и ссылок
│ ├── database.py # SQLite WAL база данных и CRUD операции
│ ├── config.py # Загрузка .env и глобальная конфигурация
│ ├── ai.py # LLM-клиент: классификация, QA-гейт, {{HOOK}}, черновики
│ └── workers/
│ ├── sender.py # Прямая отправка по MX + DKIM + Opportunistic TLS
│ ├── campaign_worker.py # Воркер рассылок с Warmup, ретраями и отпиской
│ └── ai_worker.py # Воркер AI: классификация, авто-отписка, обогащение
├── templates/ # Jinja2 HTML-шаблоны панели управления
├── static/ # Статические файлы (CSS, JS, Swagger UI assets)
├── tests/ # Функциональные тесты (изолированная БД в /tmp)
├── data/ # Хранилище (БД SQLite, приватные ключи DKIM) - ИГНОРИРУЕТСЯ В GIT
├── requirements.txt # Python-зависимости
├── Dockerfile # Контейнеризация
├── docker-compose.yml # Быстрый запуск в Docker
└── .env.example # Шаблон конфигурации окружения
-
Клонируйте репозиторий:
git clone https://github.com/your-user/mailcatch.git cd mailcatch -
Создайте файл конфигурации
.env:cp .env.example .env nano .env
-
Сгенерируйте DKIM-ключи:
mkdir -p data openssl genrsa -out data/dkim.private 2048 openssl rsa -in data/dkim.private -pubout -out data/dkim.public chmod 600 data/dkim.private
-
Запустите стек:
docker-compose up -d
-
Системные зависимости:
sudo apt update sudo apt install -y python3 python3-pip python3-venv openssl
-
Создание виртуального окружения:
cd /opt/mailcatch python3 -m venv venv source venv/bin/activate pip install -r requirements.txt
-
Генерация DKIM-ключей:
mkdir -p data openssl genrsa -out data/dkim.private 2048 openssl rsa -in data/dkim.private -pubout -out data/dkim.public chmod 600 data/dkim.private
-
Настройка конфигурации:
cp .env.example .env nano .env
-
Запуск:
# Для приёма входящих писем на 25 порт требуются права root/sudo sudo /opt/mailcatch/venv/bin/python3 main.py
| Переменная | По умолчанию | Описание |
|---|---|---|
MAILCATCH_USER |
admin |
Логин администратора для Web UI / Basic Auth |
MAILCATCH_PASSWORD |
change_this_password |
Пароль администратора. С дефолтным значением приложение не стартует |
MAILCATCH_API_KEY |
change_this_api_key |
Секретный ключ для доступа к REST API. С дефолтным значением приложение не стартует |
MAILCATCH_ALLOW_INSECURE_DEFAULTS |
— | =1 — разрешить старт с дефолтными секретами (только для разработки) |
CONFIGURED_DOMAINS |
example.com |
Список обслуживаемых доменов через запятую |
PRIMARY_DOMAIN |
example.com |
Основной домен по умолчанию |
TRACKING_BASE_URL |
http://127.0.0.1:8080 |
Публичный HTTPS URL для пикселей трекинга и отписки |
SMTP_HOST |
0.0.0.0 |
IP-адрес для прослушивания входящего SMTP |
SMTP_PORT |
25 |
Порт входящего SMTP сервера |
WEB_HOST |
127.0.0.1 |
IP-адрес для прослушивания Web UI / REST API |
WEB_PORT |
8080 |
Порт Web UI / REST API |
TRUSTED_LOCAL_IPS |
127.0.0.1,::1 |
Доверенные IP-адреса для Anti-Spoofing исключений |
TRUSTED_PROXY_IPS |
127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 |
Reverse-прокси, которым разрешено передавать заголовки клиентского IP (только от этих адресов читаются CF-Connecting-IP / X-Forwarded-For) |
DKIM_SELECTOR |
mail |
Селектор DKIM-записи (например, mail._domainkey) |
AI_ENABLED |
true |
Включение AI-ассистента (классификация, QA, {{HOOK}}, черновики) |
DASHSCOPE_API_KEY |
— | API-ключ OpenAI-совместимого LLM-эндпоинта (Qwen / DashScope) |
QWEN_BASE_URL |
https://dashscope.aliyuncs.com/compatible-mode/v1 |
Базовый URL LLM-эндпоинта |
QWEN_MODEL |
qwen3.6-flash |
Модель для AI-функций |
AI_DRAFT_CONTACTS |
— | Контактные данные, которые AI предлагает в черновиках ответов (необязательно) |
Для обеспечения 100% доставляемости и валидной проверки SPF, DKIM и DMARC настройте DNS записи вашего домена (например, example.com, сервер с IP 1.2.3.4):
mail.example.com. IN A 1.2.3.4
example.com. IN MX 10 mail.example.com.
example.com. IN TXT "v=spf1 ip4:1.2.3.4 ~all"
Получите публичный ключ:
grep -v '^-' data/dkim.public | tr -d '\n'Создайте TXT запись с селектором mail:
mail._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
_dmarc.example.com. IN TXT "v=DMARC1; p=none; sp=none; rua=mailto:postmaster@example.com"
У вашего VPS-провайдера установите PTR-запись для IP 1.2.3.4 -> mail.example.com.
curl -s "http://127.0.0.1:8080/api/messages/latest_code?to=user1@example.com" \
-H "X-API-Key: your_api_key_here"Ответ JSON:
{
"status": "success",
"data": {
"id": 142,
"recipient": "user1@example.com",
"sender": "noreply@service.com",
"subject": "Код подтверждения: 839104",
"otp_code": "839104",
"action_link": "https://service.com/verify?token=abc123xyz",
"created_at": "2026-08-21 14:30:00"
}
}curl -X POST "http://127.0.0.1:8080/api/send" \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"to_email": "client@gmail.com",
"from_email": "support@example.com",
"subject": "Тестовое сообщение с DKIM",
"body_text": "Привет! Письмо отправлено и подписано через MailCatch.",
"body_html": "<p>Привет! Письмо отправлено и подписано через <b>MailCatch</b>.</p>"
}'curl -X POST "http://127.0.0.1:8080/api/campaigns" \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Прогрев домена #1",
"from_email": "hello@example.com",
"subject": "Здравствуйте, {{NAME}}!",
"body_text": "Привет, {{NAME}}! Это проверка рассылки для {{EMAIL}}.",
"body_html": "<p>Привет, <b>{{NAME}}</b>!</p>",
"recipients": ["lead1@gmail.com", "lead2@yahoo.com"],
"warmup_initial_rate": 5,
"warmup_interval_minutes": 30,
"warmup_ramp_step": 2,
"warmup_ramp_interval_hours": 6,
"delay_seconds_min": 15,
"delay_seconds_max": 45
}'curl -X POST "http://127.0.0.1:8080/api/ai/qa" \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"subject": "Quick intro", "body_text": "Hello! ..."}'curl -X POST "http://127.0.0.1:8080/api/ai/inbound/42/send-reply" \
-H "X-API-Key: your_api_key_here"- Не коммитьте директорию
data/: она содержит базу данных с сообщениями и приватные RSA-ключи DKIM (.gitignoreуже настроен). - Не коммитьте
.env: используйте.env.exampleдля шаблона. - Nginx Reverse Proxy: для публичного доступа к Web UI рекомендуется настроить проксирование через Nginx с Let's Encrypt SSL-сертификатом.
python3 tests/test_message_build.py # Сборка исходящих писем: заголовки, MIME, инъекции, RFC 2047
python3 tests/test_bounce_handling.py # Ошибки доставки, подавление, глобальная отписка, claim/NDN/гонки
python3 tests/test_ai.py # AI-интеграция (изолированная БД, LLM выключен)
python3 tests/test_templates.py # Шаблоны писем и их использование в кампанияхПроект распространяется под свободной лицензией MIT. Подробности в файле LICENSE.



