The problem with testing password resets
Password reset flows are critical infrastructure — a broken reset email means locked-out users and support tickets. But testing them is awkward: you either send to your own Gmail (slow, cluttered), use console logging (can't verify HTML rendering), or skip testing entirely (dangerous).
With MailHog, every reset email lands in your test inbox instantly. You can verify the subject line, check that the magic link URL is correct, confirm the token is present, and preview how the email renders across clients — all without touching a real email provider.
What to verify in a password reset email
Reset link URL
Correct domain, valid token parameter, proper URL encoding.
Token expiry
Verify the token hasn't expired and the email mentions the time limit.
Mobile rendering
Reset button should be tappable on mobile — minimum 44px touch target.
Security headers
Correct From address, no reply-to pointing to external domains.
Plain text fallback
Users with plain-text email clients should still get a usable reset link.
Spam score
Reset emails landing in spam means locked-out users. Check the score.
Automate it in your test suite
The most reliable approach: trigger a password reset in your integration test, then use MailHog's API to fetch the captured email and extract the reset token. Your test can then follow the link and verify the complete flow end-to-end.
// 1. Trigger password reset
await fetch("/api/forgot-password", {
method: "POST",
body: JSON.stringify({ email: "user@test.com" }),
});
// 2. Fetch the email from MailHog
const emails = await mailhog.getMessages({ to: "user@test.com" });
const resetEmail = emails[0];
// 3. Extract the reset link
const resetUrl = resetEmail.html.match(/href="([^"]*reset[^"]*)"/)[1];
// 4. Follow the link and complete the reset
await fetch(resetUrl);
await fetch("/api/reset-password", {
method: "POST",
body: JSON.stringify({ token, newPassword: "new-secure-pw" }),
});Related use cases
Test password resets safely
Set up MailHog in 60 seconds. Free plan includes 100 emails/month.
Start free →