Zum Hauptinhalt springen

MailHog vs Mailpit: Testen von Verifizierungs- und Passwort-Zurücksetzung-E-Mails mit Casdoor

· 9 Minuten Lektüre
Yang Luo
Casdoor Maintainer

MailHog und Mailpit sind beide gefälschte SMTP-Server für die Entwicklung: Sie akzeptieren jede Nachricht, speichern sie und zeigen sie in einer Web-UI an, statt sie zuzustellen. Beide verwenden dieselben Standardports, SMTP auf 1025 sowie Web-UI und API auf 8025, sodass die SMTP-Adresse smtp://127.0.0.1:1025 ist und der Posteingang sich unter http://127.0.0.1:8025 befindet. Der Unterschied liegt in der Wartung: Die letzte Veröffentlichung von MailHog, v1.0.1, erschien im August 2020, während Mailpit v1.33.0 am 31. Oktober 2026 veröffentlichte. Verwenden Sie Mailpit für neue Projekte. Casdoor sendet an beide über einen einfachen SMTP-Provider, sodass Sie Registrierungscodes, Passwort-Zurücksetzungs-E-Mails und Magic Links ohne ein echtes Mail-Konto testen können.

MailHog vs Mailpit auf einen Blick​

MailHogMailpit
Letzte Veröffentlichungv1.0.1, 2020-08-11v1.33.0, 2026-10-31
Letzter Commit im Standard-Branch2022-08-022026-10-31
LizenzMITMIT
Standard-SMTP-Port10251025
Standard-Port für Web-UI und API80258025
Docker-Imagemailhog/mailhog, nur amd64axllent/mailpit, amd64, arm64 und 386
HTTP-APIv1 und v2: list, get, delete, Suche nach from, to oder containingv1: list, get, delete, Suche mit Filtern wie to: und subject:, Verknüpfung zur neuesten Nachricht (latest)
Standard-SpeicherIm Speicher (In Memory)Temporäre SQLite-Datenbank, wird beim Beenden gelöscht
Persistenter SpeicherMongoDB oder MaildirSQLite-Datei (MP_DATABASE) oder rqlite
NachrichtenlimitKeines dokumentiertBehält standardmäßig die neuesten 500 Nachrichten (MP_MAX_MESSAGES)
HTML-Prüfung, Link-Prüfung, Spam-PrüfungNeinJa
Webhook bei neuer E-MailNeinJa (MP_WEBHOOK_URL)
SMTP TLSNicht angebotenOptional STARTTLS oder SSL/TLS
FehlerinjektionJimChaos
Nachricht an einen echten SMTP-Server sendenJaJa
POP3-ServerNeinJa, optional
Basic Auth für die Web-UIJaJa

Die Zahlen auf Docker Hub zeigen, dass viele Leute immer noch MailHog beziehen. Das spiegelt alte Tutorials und CI-Dateien wider, nicht aber Aktivität: Ein offenes Issue im MailHog-Repository mit dem Titel "THIS PROJECT IS DEAD!" hat eine Antwort des Autors aus dem Jahr 2023, in der er sagt, dass er keine Zeit mehr habe, es zu pflegen. Die README von Mailpit beschreibt sich selbst als inspiriert von MailHog und verweist auf denselben Kommentar.

Die Architektur des Images ist wichtiger, als es scheint. Auf einem Apple Silicon Laptop oder einem ARM-CI-Runner läuft mailhog/mailhog nur unter Emulation, während axllent/mailpit ein natives arm64-Image hat.

Führen Sie beide mit Docker aus​

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 speichert E-Mails in einer temporären Datenbank, die verschwindet, wenn der Container stoppt. Um sie über Neustarts hinweg zu behalten, mounten Sie ein Volume und setzen Sie 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

Ohne Docker funktionieren sowohl brew install mailhog als auch brew install mailpit auf macOS, und Mailpit bietet statische Binaries für Windows, Linux und macOS auf seiner Release-Seite an.

Führen Sie es in GitHub Actions als Service-Container neben Ihrem Test-Job aus:

services:
mailpit:
image: axllent/mailpit
ports:
- 1025:1025
- 8025:8025

Casdoor auf MailHog oder Mailpit konfigurieren​

Casdoor hat keinen separaten Provider-Typ für MailHog oder Mailpit, und das braucht es auch nicht. Der E-Mail-Typ Default sendet über SMTP, und beide Tools sind SMTP-Server.

  1. Als globaler Administrator fügen Sie einen Provider in der Organisation admin oder built-in hinzu.
  2. Legen Sie Category auf Email und Type auf Default fest.
  3. Setzen Sie Host auf den Ort, an dem das Tool ausgeführt wird, und Port auf 1025.
  4. Lassen Sie Username und Password leer.
  5. Klicken Sie auf Test SMTP Connection, dann auf Send Testing Email, und prüfen Sie die Web-UI auf Port 8025.

Die Schritt-für-Schritt-Anleitungen mit Screenshots sind Test email with MailHog und Test email with Mailpit.

Einige Details entscheiden darüber, ob dies beim ersten Versuch funktioniert:

Lassen Sie den SSL-Modus auf Auto oder setzen Sie ihn auf Disable. Im Modus Auto verwendet Casdoor implizites TLS nur auf Port 465 und führt ein Upgrade mit STARTTLS durch, nur wenn der Server dies anbietet. Weder MailHog noch ein Standard-Mailpit bieten STARTTLS auf Port 1025 an, daher bleibt die Verbindung unverschlüsselt (plain). Wählen Sie nicht Enable: Dies erzwingt implizites TLS, und der Handshake schlägt gegen einen Plain-Text-Server fehl. Die Tabelle zum SSL-Modus enthält das vollständige Verhalten.

Lassen Sie die Zugangsdaten leer. Casdoor meldet sich nur beim SMTP-Server an, wenn Username gesetzt ist. Wenn Sie es ausfüllen, verweigert Go's PLAIN-Authentifizierung das Senden des Passworts über eine unverschlüsselte Verbindung, es sei denn, der Host ist localhost. Daher schlägt eine MailHog-Instanz unter 192.168.x.x mit einem Authentifizierungsfehler fehl, obwohl MailHog jede Anmeldung akzeptieren würde. Mailpit fragt standardmäßig überhaupt nicht nach Authentifizierung.

Verwenden Sie den richtigen Host. 127.0.0.1 funktioniert nur, wenn Casdoor und der Mail-Catcher auf derselben Maschine laufen. Wenn beide in Docker Compose laufen, verwenden Sie den Service-Namen, z. B. mailpit, als Host.

Verwenden Sie einen globalen Provider. Ein Provider, der einer normalen Organisation gehört, darf möglicherweise nur Internet-Adressen erreichen und kann sich daher nicht mit 127.0.0.1 oder einer privaten IP verbinden. Provider in admin oder built-in sind nicht eingeschränkt. Siehe Which addresses a provider can reach.

Setzen Sie origin für Links. Bestätigungscodes funktionieren sofort. Links zur Passwortzurücksetzung und Magic Links benötigen, dass Casdoor seine öffentliche URL kennt, entweder über origin in conf/app.conf oder eine Anfrage auf einem Loopback-Host. Andernfalls wird der Reset-Link aus der E-Mail entfernt und Magic Links schlagen fehl. Siehe Templates.

Fügen Sie abschließend den Provider zu Ihrer Anwendung hinzu unter Add providers to an application, damit Registrierung und Passwortzurücksetzung ihn tatsächlich nutzen.

Bestätigungscode in einem automatisierten Test lesen​

Casdoors Bestätigungscodes bestehen aus sechs Ziffern, und das Standard-Template lautet "Here is your code: " gefolgt vom Code. Ein End-to-End-Test registriert einen Benutzer, bittet Casdoor, den Code zu senden, und liest ihn dann über die API des Mail-Catchers aus.

Bei Mailpit suchen Sie nach dem Empfänger und öffnen Sie den neuesten Treffer. GET /api/v1/search gibt Treffer absteigend nach Datum zurück, und GET /api/v1/message/{ID} gibt die geparsten Text- und HTML-Bodies zurück:

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}`);
}

Wenn nur ein Test gleichzeitig E-Mails sendet, überspringt GET /api/v1/message/latest den Suchschritt. Vor jedem Test leert DELETE /api/v1/messages ohne Body das Postfach.

Bei MailHog ist der nächste Aufruf GET /api/v2/search?kind=to&query=<address>. Die Nachrichten werden in items beginnend mit der neuesten zurückgegeben, und der Inhalt befindet sich in 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 ist der rohe MIME-Body. Casdoor sendet im quoted-printable-Format, daher wird = zu =3D, und lange Zeilen erhalten weiche Umbrüche, die mit = enden. Dekodieren Sie dies zuerst oder halten Sie den Code am Anfang einer kurzen Vorlage. Leeren Sie MailHog mit DELETE /api/v1/messages.

Migration von MailHog zu Mailpit​

Da die Ports übereinstimmen, sind die meisten Migrationen eine Einzeilige Änderung in docker-compose.yml: Ersetzen Sie mailhog/mailhog durch axllent/mailpit. Der Provider von Casdoor behält denselben Host und Port bei. Was sich ändert:

  • Einstellungen. MailHog liest MH_* Variablen; Mailpit liest MP_*. Wenn Sie MH_STORAGE=maildir oder MongoDB verwendet haben, wechseln Sie zu MP_DATABASE.
  • Test-Helferprogramme. Mailpit hat keine /api/v2 Endpunkte. Schreiben Sie Aufrufe an /api/v2/messages und /api/v2/search für /api/v1/messages und /api/v1/search um und lesen Sie messages[].ID sowie Text oder HTML anstelle von items[].Content.Body. Das quoted-printable-Dekodieren entfällt.
  • Suchsyntax. kind=to&query=a@example.com wird zu query=to:"a@example.com".
  • Fehlerinjektion. Jim hat in Mailpit keine Flags; verwenden Sie Chaos.
  • Authentifizierung. Wenn eine App darauf besteht, sich über unverschlüsseltes SMTP anzumelden, starten Sie Mailpit mit MP_SMTP_AUTH_ACCEPT_ANY=1 und MP_SMTP_AUTH_ALLOW_INSECURE=1. Für Casdoor ist es einfacher, die Anmeldedaten leer zu lassen.
  • Aufbewahrungsdauer. Mailpit löscht standardmäßig auf die neuesten 500 Nachrichten. Erhöhen Sie MP_MAX_MESSAGES, wenn ein langer Testlauf mehr benötigt.

Übergang zur Produktion​

MailHog und Mailpit liefern niemals E-Mails an echte Postfächer aus, es sei denn, Sie geben Nachrichten manuell frei, daher benötigt die Produktion einen echten Provider. In Casdoor tauschen Sie den Provider aus, nicht die Vorlagen. Die E-Mail-Vorlagen, der %s Code-Platzhalter und der <reset-link> Block bleiben gleich:

Ein häufiges Setup hält Mailpit in Entwicklung und CI und den echten Provider in der Produktion. Jede Umgebung zeigt ihre Anwendung auf einen anderen Provider, sodass der Anmeldeprozess, den Sie testen, auch der ist, der ausgeliefert wird.

Referenzen​