Email Testing Should Be as Easy as Unit Testing
Every other part of your application has tests. Your API endpoints have integration tests. Your database queries have unit tests. Your business logic has coverage reports. But email? You deploy, open Gmail, trigger a password reset, and squint at the inbox. That is not testing. That is hoping.
The worst part is that nobody calls it out. Teams celebrate 90% code coverage and ship welcome emails they have never once verified in an automated test.
The Problem with How We Test Email Today
Most teams fall into one of three patterns. The first group skips email testing entirely. The second group manually fires off emails to a personal inbox and eyeballs the result. The third group sets up a tool like MailHog or Mailtrap as a separate, manual step that lives outside the CI pipeline, requires its own setup, and gets forgotten the moment someone changes a template.
None of these are testing. They are rituals that create the feeling of safety without the substance.
Here is what actually happens in practice. The test suite runs. The API tests pass. The build goes green. But nobody verified that the welcome email renders correctly after last week's template refactor. Nobody confirmed the password reset link still contains the right token format. Nobody checked that the order confirmation includes the right line items when the cart has a discount applied.
These are not edge cases. These are the exact flows users hit on their first day with your product. And they break in production because CI/CD pipelines treat email as an afterthought, not a first-class integration.
The deeper problem is structural. Email flows combine backend logic, third-party infrastructure, template rendering, and timing constraints. As BugBug's analysis of email testing tools notes, a small change like an updated template, a backend refactor, or a configuration tweak can silently break the entire flow. Email is among the most fragile components in an application, and yet it gets the least systematic testing.
The Insight: Email Is Just Another Integration
Here is the realization that changes things. Email is an integration, the same as any other. You would not test a Stripe integration by manually triggering a charge and checking your bank account. You would create a test environment, call the API, assert on the response. Email should work exactly the same way.
The reason it does not come down to tooling. Traditionally, testing email properly meant setting up a separate SMTP-catching server, dealing with its own authentication, running it as a sidecar in your CI environment, and writing glue code to pull messages out of it. That friction is why teams skip it. The path of least resistance has always been the personal inbox.
Sandbox inboxes remove that friction. The pattern is simple: create a temporary inbox programmatically, send your email to that address, read the messages back through an API, assert on the content, tear it down. No SMTP server to configure. No separate tool to maintain. Just API calls inside your test file, running in the same CI job as everything else.
The Solution: First-Class Email Tests with mailbot
mailbot's sandbox inboxes are built for exactly this workflow. On the free tier you get 5 inboxes and 5,000 emails per month, which covers the test suite of any team getting started. Each inbox is created programmatically, has its own address, and is readable through the same API you use for everything else.
Here is what a complete email test looks like in a Node.js test suite:
import { MailBot } from '@yopiesuryadi/mailbot-sdk';
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
const client = new MailBot({ apiKey: process.env.MAILBOT_API_KEY });
describe('Welcome email flow', () => {
let testInbox;
beforeAll(async () => {
// Create a disposable inbox for this test run
testInbox = await client.request('POST', '/v1/inboxes', {
name: 'welcome-email-test'
});
});
it('sends a welcome email with the correct subject and body', async () => {
// Trigger your app's welcome email flow
await triggerWelcomeEmail({ to: testInbox.address });
// Give delivery a moment, then fetch messages
await new Promise(resolve => setTimeout(resolve, 1500));
const messages = await client.messages.list(testInbox.id, {
direction: 'inbound'
});
expect(messages.length).toBeGreaterThan(0);
const welcome = messages[0];
expect(welcome.subject).toBe('Welcome to the platform');
expect(welcome.bodyText).toContain('Get started');
expect(welcome.bodyText).toContain(testInbox.address);
});
afterAll(async () => {
// Clean up the inbox when done
await client.request('DELETE', `/v1/inboxes/${testInbox.id}`);
});
});
That is the full test. Create inbox, trigger email, list messages, assert on subject and body, tear down. It runs in CI. It runs in the same job as your unit tests. It produces a pass or fail result that gates your deployment.
You can do the same for password reset flows, order confirmations, notification emails, any email your application sends. Each test gets its own inbox, which means tests do not bleed into each other. The assertions are explicit. The feedback is immediate.
The Mailsac team's guide to CI/CD email testing captures the core requirement well: your email testing tool needs to capture messages and expose them through an API with predictable behavior. Gmail and Outlook do not satisfy that. A properly designed sandbox inbox does.
Ship with Confidence, Not Hope
This is ultimately not about catching bugs, though it will catch bugs. It is about changing the category of thing email is in your mental model.
Right now email lives in the "probably fine" bucket. You change a template, deploy, and assume it still works because nothing broke last time. That assumption has a cost. It accumulates as unverified behavior that ships to production and breaks for the first user who hits it.
When your email tests run in CI alongside your unit tests and integration tests, that assumption goes away. The welcome email is verified on every push. The password reset flow is asserted in code. You do not ship and hope. You ship and know.
Explore mailbot's sandbox inboxes and get your first email test running today.