Why test emails in Node.js with MailHog?
Node.js applications send emails for password resets, order confirmations, magic links, and notifications. Without a test SMTP server, you either send to real addresses (risky), use console logging (incomplete), or skip email testing entirely. MailHog captures every email with full MIME parsing so you can verify content, headers, and rendering without any risk.
Quickstart: Nodemailer + MailHog
Install Nodemailer and configure it to use MailHog's SMTP server:
npm install nodemailer
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST || "smtp.mailhog.site",
port: parseInt(process.env.SMTP_PORT || "2525"),
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
// Send a test email
await transporter.sendMail({
from: "app@yourcompany.com",
to: "user@example.com",
subject: "Reset your password",
html: "<h1>Password Reset</h1><p>Click the link below...</p>",
});
// Email is now visible in your MailHog dashboard ✅Environment configuration
Add these to your .env file:
SMTP_HOST=smtp.mailhog.site SMTP_PORT=2525 SMTP_USER=your-inbox-username SMTP_PASS=your-inbox-password
Testing with Jest
Use MailHog's API to assert on captured emails in your test suite:
test("sends password reset email", async () => {
// Trigger password reset in your app
await request(app)
.post("/api/forgot-password")
.send({ email: "user@test.com" });
// Check MailHog for the email
const res = await fetch(
`${MAILHOG_URL}/api/v1/inbox/${INBOX_ID}/messages`,
{ headers: { "X-API-Key": API_KEY } }
);
const { data } = await res.json();
expect(data[0].subject).toBe("Reset your password");
expect(data[0].to[0].address).toBe("user@test.com");
expect(data[0].html).toContain("Reset Password");
});Common pitfalls with Nodemailer
- Forgetting to set
secure: falsewhen using port 2525 (not TLS by default) - Using
tls.rejectUnauthorized: falsein development but shipping it to production - Hardcoding SMTP credentials instead of using environment variables
- Not testing multipart emails (HTML + plain text fallback)