Каждая команда, делающая почтовые фичи, рано или поздно упирается в одну развилку: направить разработку на реального SMTP-провайдера или сфейкать почтовый слой и надеяться, что продакшен поведёт себя. Первый вариант утекает кредами, сжигает квоту провайдера и иногда отправляет настоящему клиенту письмо с ноутбука. Второй не тестирует ничего дальше точки, где ваш код отдаёт сообщение серверу. Есть и лучший средний путь — даже несколько. Вот как соотносятся стандартные варианты локального тестирования и когда каждый выигрывает.
Почему реальный SMTP в разработке — плохая идея
Искушение понятно: настоящий провайдер, настоящее поведение, ноль настройки. Расплата приходит позже:
- Утечка кредов. API-ключи, живущие в .env-файлах на машинах разработчиков, заканчиваются в логах, скриншотах и в итоге в чате.
- Случайные реальные отправки. Тестовый прогон по скопированной продакшен-базе рассылает письма реальным пользователям с вашего ноутбука. Это происходит постоянно, и это всегда запоминается.
- Флейковые тест-сьюты. Когда юнит-тесты зависят от аптайма стороннего провайдера, его rate-лимитов и причуд песочницы, CI превращается в прогноз погоды.
- Стоимость и квоты. Даже щедрые бесплатные тарифы утекают быстро, когда сьют отправляет сотни сообщений за прогон.
Решение — вообще не пускать реальную отправку во внутренний цикл; аргументация из статьи тестирование с временной почтой для разработчиков и QA применима и к локальной разработке.
Вариант 1: catch-all локальные SMTP-серверы (MailHog, Mailpit)
Catch-all-сервер слушает на локальном порту, принимает всё без авторизации и TLS, хранит сообщения в памяти и показывает их в веб-интерфейсе. Ваше приложение указывает на него как на любой SMTP-хост:
SMTP_HOST=127.0.0.1 SMTP_PORT=1025
docker run -p 1025:1025 -p 8025:8025 axllent/mailpit
Mailpit — текущий поддерживаемый стандарт: HTML-превью, разбор MIME, REST API для ассертов и chaos-режим, симулирующий сбои и задержки. MailHog, его предшественник, не поддерживается с 2020 года, но всё ещё работает и всё ещё мелькает в бесчисленных туториалах; для всего нового берите Mailpit.
Побеждает в: юнит- и интеграционных тестах, фронтенд-работе, где дизайнерам нужно видеть письма, и на ноутбуках в поездах вообще без сети.
Вариант 2: контейнерные SMTP-хранилища в dev-стеке
Следующая ступень встраивает почтовое хранилище в ваш docker-compose dev-стек как именованный сервис с персистентным volume. Улучшаются две вещи:
- Общее состояние. Почта всех разработчиков лежит в одном предсказуемом месте, и перезапуск приложения не стирает ящик.
- Тестовые ассерты через API. Mailpit открывает REST API, поэтому интеграционные тесты могут забрать последнее письмо, отправленное на адрес, и заассертить тему, заголовки и тело без парсинга логов.
Компромисс прежний: почта никогда не покидает машину. Аутентификация, DNS и реальная доставляемость остаются непротестированными, поэтому зелёный сьют всё ещё может зашипить отправителя со сломанной записью. Перед подключением staging к реальным доменам проверьте и принимающую сторону — MX-чекер показывает почтовые обменники для любого домена, которому вы собираетесь писать.
Вариант 3: одноразовые ящики для реализма staging
Локальные хранилища не могут ответить на вопрос, дошло ли сообщение реально через настоящий интернет. Для этого вопроса нужна реальная доставка — и здесь одноразовые ящики отрабатывают сполна. Направьте staging на реальную отправляющую инфраструктуру и используйте временные адреса как получателей: сообщения проходят настоящий DNS, TLS и фильтрацию провайдеров, и вы можете ассертить время прибытия, контент и попадание в спам, а не только собственный исходящий лог.
Этот подход сияет для:
- Сквозных потоков регистрации. Ссылки подтверждения и одноразовые коды, проверяемые со стороны ящика, с паттерном автоматизации из статьи автоматизация email-тестирования через API временной почты.
- Пайплайнов вебхуков. Вебхуки bounce-ей и входящих сообщений требуют реальных почтовых событий для тестирования; наше руководство как получать вебхуки из временного ящика разбирает схему подключения.
- Предпродакшен-репетиций. Более полная настройка staging разобрана в статье тестирование в staging-среде.
Какой вариант когда
- Локальные юнит-тесты и превью: Mailpit на localhost. Быстро, офлайн, без побочных эффектов.
- Командная dev-среда: Mailpit как compose-сервис с volume. Общее, инспектируемое, ассертится через API.
- Staging и релизная верификация: реальная отправка плюс одноразовые ящики получателей. Единственный вариант, прогоняющий реальный путь почты ваших пользователей.
- Мониторинг продакшена: вообще не локальная тема — там вступают проверки размещения и seed-тесты.
Относитесь к этому как к слоям, а не конкурентам: большинство зрелых настроек гоняют все три, каждый на своей высоте.
FAQ
MailHog всё ещё хороший выбор в 2026 году? Он работает, но не поддерживается годами и отстаёт в современном обработке MIME. Mailpit — его активно развиваемый наследник с совместимым набором функций; выбирайте его для всего нового.
Можно ли тестировать DKIM и SPF с локальным SMTP-сервером? Нет. Аутентификация включает DNS и lookup публичных ключей, которые localhost-сервер никогда не затрагивает. Используйте реальную доставку на одноразовые адреса, затем проверяйте подписи на полученном сообщении.
Как остановить отправку писем реальным людям из dev-среды? Направьте её на локальный SMTP или используйте staging-флаг, переписывающий всех получателей на одноразовые ящики. Никогда не держите продакшен-креды на пути, достижимом из dev.
Какой самый дешёвый способ заассертить прибытие письма в CI? Создайте временный ящик через API, триггерните отправку, опросите сообщение и зафейлите билд по таймауту. Это несколько строк скрипта, и это ловит сбои, которые локальные хранилища не видят.
