MailHog vs Mailpit: тестування листів верифікації та скидання пароля з Casdoor
MailHog і Mailpit — це фальшиві SMTP-сервери для розробки: вони приймають усі повідомлення, зберігають їх і показують у веб-інтерфейсі замість доставки. Обидва використовують ті самі порти за замовчуванням, SMTP на 1025 та веб-інтерфейс і API на 8025, тому адреса SMTP — smtp://127.0.0.1:1025, а скринька знаходиться за адресою http://127.0.0.1:8025 для обох. Відмінність полягає в підтримці: останній реліз MailHog, v1.0.1, вийшов у серпні 2020 року, тоді як Mailpit випустив v1.33.0 31 жовтня 2026 року. Для нового проекту використовуйте Mailpit. Casdoor надсилає листи через звичайного SMTP-провайдера до обох, тому ви можете тестувати коди реєстрації, листи для скидання пароля та магічні посилання без реального поштового акаунта.
MailHog vs Mailpit коротко
| MailHog | Mailpit | |
|---|---|---|
| Останній реліз | v1.0.1, 2020-08-11 | v1.33.0, 2026-10-31 |
| Останній коміт у гілці за замовчуванням | 2022-08-02 | 2026-10-31 |
| Ліцензія | MIT | MIT |
| Стандартний порт SMTP | 1025 | 1025 |
| Стандартний порт веб-інтерфейсу та API | 8025 | 8025 |
| Образ Docker | mailhog/mailhog, лише amd64 | axllent/mailpit, amd64, arm64 і 386 |
| HTTP API | v1 і v2: список, отримання, видалення, пошук за from, to або containing | v1: список, отримання, видалення, пошук із фільтрами, такими як to: і subject:, ярлик для останнього повідомлення (latest) |
| Стандартне сховище | У пам'яті | Тимчасова база даних SQLite, видаляється при виході |
| Стійке зберігання | MongoDB або Maildir | Файл SQLite (MP_DATABASE) або rqlite |
| Обмеження кількості повідомлень | Не задокументовано | За замовчуванням зберігає 500 найновіших (MP_MAX_MESSAGES) |
| Перевірка HTML, посилань, спаму | Ні | Так |
| Webhook для нової пошти | Ні | Так (MP_WEBHOOK_URL) |
| TLS для SMTP | Не пропонується | Опціональний STARTTLS або SSL/TLS |
| Імітація збоїв | Jim | Chaos |
| Надсилання повідомлення на реальний сервер SMTP | Так | Так |
| Сервер POP3 | Ні | Так, опціонально |
| Базова автентифікація для веб-інтерфейсу | Так | Так |
Лічильники завантажень на Docker Hub показують, що багато людей досі використовують MailHog. Це відображає старі підручники та файли CI, а не активність: у відкритому питанні (issue) у репозиторії MailHog із назвою "THIS PROJECT IS DEAD!" є відповідь автора з 2023 року, де він каже, що більше не має часу на підтримку проєкту. README Mailpit описує його як натхненний MailHog і посилається на той самий коментар.
Архітектура образу важливіша, ніж здається. На ноутбуках Apple Silicon або ARM-раннерах CI mailhog/mailhog працює лише в режимі емуляції, тоді як axllent/mailpit має нативний образ arm64.
Запуск будь-якого з них через Docker
MailHog:
docker run -d --name mailhog -p 1025:1025 -p 8025:8025 mailhog/mailhog
Mailpit:
docker run -d --name mailpit -p 1025:1025 -p 8025:8025 axllent/mailpit
Mailpit зберігає листи в тимчасовій базі даних, яка зникає після зупинки контейнера. Щоб зберегти їх між перезапусками, монтируйте том і встановіть MP_DATABASE:
docker run -d --name mailpit \
-v "$PWD/mailpit-data:/data" \
-e MP_DATABASE=/data/mailpit.db \
-p 1025:1025 -p 8025:8025 \
axllent/mailpit
Без Docker, brew install mailhog і brew install mailpit обидва працюють на macOS, а Mailpit також надає статичні бінарні файли для Windows, Linux і macOS на своїй сторінці випусків.
У GitHub Actions запустіть його як сервісний контейнер поруч із вашим тестовим завданням:
services:
mailpit:
image: axllent/mailpit
ports:
- 1025:1025
- 8025:8025
Налаштування Casdoor для роботи з MailHog або Mailpit
Casdoor не має окремого типу провайдера для MailHog або Mailpit, і йому це не потрібно. Тип email Default надсилає листи через SMTP, а обидва інструменти є серверами SMTP.
- Як глобальний адміністратор, додайте провайдер в організацію
adminабоbuilt-in. - Встановіть Category як
Email, а Type — якDefault. - Встановіть Host на адресу, де працює інструмент, і Port на
1025. - Залиште поля Username і Password порожніми.
- Натисніть Test SMTP Connection, потім Send Testing Email і перевірте веб-інтерфейс на порту 8025.
Покрокові інструкції зі скріншотами доступні тут: Тестування email з MailHog та Тестування email з Mailpit.
Кілька деталей визначають, чи спрацює це з першої спроби:
Залиште режим SSL на Auto або встановіть Disable. У режимі Auto Casdoor використовує неявний TLS лише на порту 465 і переходить на STARTTLS, лише якщо сервер це пропонує. Ні MailHog, ні стандартний Mailpit не пропонують STARTTLS на порту 1025, тому з'єднання залишається незашифрованим. Не обирайте Enable: це примусово вмикає неявний TLS, і рукостискання (handshake) завершиться помилкою проти текстового сервера. Повну поведінку описано в таблиці режимів SSL.
Залиште облікові дані порожніми. Casdoor виконує вхід до сервера SMTP лише якщо вказано Username. Якщо ви заповните це поле, автентифікація PLAIN у Go відмовиться надсилати пароль через незашифроване з'єднання, якщо хост не localhost. Тому MailHog на адресі 192.168.x.x видасть помилку автентифікації, хоча MailHog прийняв би будь-який логін. Mailpit за замовчуванням взагалі не вимагає автентифікації.
Використовуйте правильний хост. 127.0.0.1 працює лише коли Casdoor і перехоплювач пошти працюють на одній машині. Якщо обидва запускаються в Docker Compose, використовуйте ім'я сервісу, наприклад mailpit, як хост.
Використовуйте глобальний провайдер. Провайдер, що належить звичайній організації, може звертатися лише до інтернет-адрес, тому він не зможе підключитися до 127.0.0.1 або приватної IP-адреси. Провайдери в admin або built-in не мають таких обмежень. Дивіться Які адреси можуть бути досяжні провайдером.
Встановіть origin для посилань. Коди верифікації працюють одразу. Посилання для скидання пароля та магічні посилання потребують того, щоб Casdoor знав свою публічну URL-адресу, через параметр origin у conf/app.conf або запит з локального хоста (loopback). В іншому випадку посилання для скидання буде пропущено в листі, а магічні посилання не працюватимуть. Дивіться Шаблони.
Нарешті, додайте провайдер до вашого додатка в розділі Додавання провайдерів до додатка, щоб реєстрація та скидання пароля дійсно використовували його.
Читання коду верифікації в автоматизованому тесті
Коди верифікації Casdoor складаються з шести цифр, і стандартний шаблон містить текст "Here is your code: ", за яким йде код. Енд-to-end тест реєструє користувача, просить Casdoor надіслати код, а потім зчитує його з API перехоплювача пошти.
У Mailpit шукайте за отримувачем і відкрийте найновіший результат. GET /api/v1/search повертає результати від найновіших до найстаріших, а GET /api/v1/message/{ID} повертає розібрані тіла Text і HTML:
import { request } from "@playwright/test";
const MAILPIT = process.env.MAILPIT_URL ?? "http://127.0.0.1:8025";
export async function latestCode(to: string): Promise<string> {
const api = await request.newContext({ baseURL: MAILPIT });
for (let i = 0; i < 20; i++) {
const res = await api.get("/api/v1/search", {
params: { query: `to:"${to}"`, limit: "1" },
});
const { messages } = await res.json();
if (messages.length > 0) {
const msg = await (await api.get(`/api/v1/message/${messages[0].ID}`)).json();
const match = (msg.Text || msg.HTML).match(/code: (\d{6})/);
if (match) return match[1];
}
await new Promise((r) => setTimeout(r, 500));
}
throw new Error(`no verification email for ${to}`);
}
Якщо лише один тест надсилає лист за раз, GET /api/v1/message/latest пропускає крок пошуку. Перед кожним тестом виклик DELETE /api/v1/messages без тіла запиту очищує вхідні повідомлення.
У MailHog найближчий аналог — це GET /api/v2/search?kind=to&query=<address>. Повідомлення повертаються у полі items від найновіших до найстаріших, а текст листа міститься в items[0].Content.Body:
const res = await api.get("/api/v2/search", {
params: { kind: "to", query: to, limit: "1" },
});
const { items } = await res.json();
const body: string = items[0]?.Content.Body ?? "";
Content.Body містить сирий MIME-тіло. Casdoor використовує кодування quoted-printable, тому символ = перетворюється на =3D, а довгі рядки мають м’які переноси, що закінчуються на =. Спочатку декодуйте його або розміщуйте код на початку короткого шаблону. Очистіть MailHog командою DELETE /api/v1/messages.
Міграція з MailHog на Mailpit
Оскільки порти збігаються, більшість міграцій полягають у однорядковій зміні в docker-compose.yml: замініть mailhog/mailhog на axllent/mailpit. Провайдер Casdoor залишає той самий хост і порт. Що змінюється:
- Налаштування. MailHog читає змінні
MH_*; Mailpit читаєMP_*. Якщо ви використовувалиMH_STORAGE=maildirабо MongoDB, перейдіть наMP_DATABASE. - Тестові допоміжні функції. Mailpit не має ендпоінтів
/api/v2. Перепишіть виклики до/api/v2/messagesта/api/v2/searchна/api/v1/messagesта/api/v1/search, і читайтесьmessages[].IDплюсTextабоHTMLзамістьitems[].Content.Body. Декодування quoted-printable більше не потрібне. - Синтаксис пошуку.
kind=to&query=a@example.comзмінюється наquery=to:"a@example.com". - Імітація збоїв. У Jim немає прапорців для Mailpit; використовуйте Chaos.
- Автентифікація. Якщо додаток наполягає на вході через незахищений SMTP, запустіть Mailpit зі змінними
MP_SMTP_AUTH_ACCEPT_ANY=1таMP_SMTP_AUTH_ALLOW_INSECURE=1. Для Casdoor простіше залишити облікові дані порожніми. - Зберігання даних. За замовчуванням Mailpit видаляє старі повідомлення, залишаючи лише 500 найновіших. Збільште
MP_MAX_MESSAGES, якщо тривалий тестовий прогон потребує більше місця.
Перехід до продуктивного середовища
MailHog і Mailpit ніколи не доставляють листи на реальні поштові скриньки, якщо ви вручну не випускаєте повідомлення, тому для продуктивного середовища потрібен реальний провайдер. У Casdoor ви замінюєте провайдера, а не шаблони. Шаблони електронної пошти, заповнювач %s для коду та блок <reset-link> залишаються незмінними:
- Будь-який SMTP-сервер із типом
Default, описаний у Email providers - SendGrid та Resend через їхні API
- Brevo через його SMTP-релей
- Azure Communication Services
- Власний HTTP-ендпоінт із Custom HTTP Email
Поширена конфігурація: Mailpit залишається в середовищі розробки та CI, а реальний провайдер — у продуктивному середовищі. Кожне середовище вказує свій додаток на різного провайдера, тому потік реєстрації, який ви тестуєте, є тим самим, що й у продакшені.
Посилання
- Репозиторій MailHog та README: https://github.com/mailhog/MailHog
- Конфігурація MailHog та документація API v1/v2: https://github.com/mailhog/MailHog/tree/master/docs
- Коментар щодо підтримки MailHog: https://github.com/mailhog/MailHog/issues/442#issuecomment-1493415258
- Репозиторій Mailpit та README: https://github.com/axllent/mailpit
- Документація Mailpit (Docker, сховище, SMTP, вебхук, фільтри пошуку): https://mailpit.axllent.org/docs/
- Довідник Mailpit API v1: https://mailpit.axllent.org/docs/api-v1/
- Код email-провайдера Casdoor: https://github.com/casdoor/casdoor/tree/master/email