If you're a software engineer, you know the pain: testing user signup flows means creating dozens of throwaway email accounts every single day. You fill out the form, wait for the verification email, click the link, and repeat—50, 100, sometimes 200 times during a sprint.
Using test+1[at]gmail.com, test+2[at]gmail.com works for a while, but what happens when you need to test:
- Unique email constraints (does your DB reject duplicates?)
- Actual email delivery (is your SendGrid config correct?)
- Email content parsing (does the OTP extraction work?)
- Rate limiting (can users create 10 accounts from the same email?)
The Gmail + trick fails in all these scenarios. You need real, disposable email addresses that behave like actual user inboxes.
The Problem with Manual Testing
Let's be honest: manual email testing is a productivity killer.
Time Waste
Creating a test account manually takes 30-60 seconds. If you're testing 50 times a day, that's 25-50 minutes of pure waste—time you could spend writing code or fixing bugs.
Human Error
Manually copying verification links is error-prone. You might copy the wrong link, miss a character, or accidentally click an unsubscribe link instead of the verify button.
Inconsistent Test Data
When you manually create test accounts, you introduce variability. One test uses test1[at]gmail.com, another uses johndoe[at]example.com. This makes it hard to reproduce bugs and analyze test results.
Can't Test Edge Cases
How do you test what happens when a user signs up with a 64-character email address? Or an email with special characters like user+tag[at]sub.domain.com? Manual testing makes these scenarios impractical.
Enter the Temporary Mail API
Temporary Mail Online offers a developer-first API designed specifically for automated testing.
Key Features for QA Engineers
1. Instant Inbox Creation
POST https://temporary-mail.online/api/inbox/create
Response:
{
"id": "x8k29a",
"email": "x8k29a[at]temporary-mail.online",
"expiresAt": "2026-02-10T10:00:00Z"
}
Create a fresh inbox in under 50ms. No rate limits for authenticated users.
2. Real-Time Message Retrieval
GET https://temporary-mail.online/api/inbox/messages?id=x8k29a
Response:
{
"messages": [
{
"id": "msg_abc123",
"from": "noreply[at]yourapp.com",
"subject": "Verify your email",
"body": {
"text": "Your verification code is: 123456",
"html": "<p>Your verification code is: <strong>123456</strong></p>"
},
"receivedAt": "2026-02-09T10:01:23Z"
}
]
}
Get messages as JSON with parsed HTML, plain text, and attachments. No need to parse MIME types yourself.
3. Server-Sent Events (SSE) for Real-Time Updates
GET https://temporary-mail.online/api/inbox/sse?id=x8k29a
Stream events as emails arrive:
event: message
data: {"id": "msg_abc123", "subject": "Verify your email", ...}
Perfect for long-running E2E tests where you need to wait for an email without polling.
4. Webhook Support (Coming Soon)
Register a webhook URL and we'll POST to it when emails arrive. Ideal for CI/CD pipelines.
Real-World Use Cases
Use Case 1: Playwright E2E Testing
import { test, expect } from '@playwright/test';
test('user signup flow', async ({ page }) => {
// 1. Create temporary inbox
const inbox = await fetch('https://temporary-mail.online/api/inbox/create')
.then(r => r.json());
const email = inbox.email; // e.g., x8k29a[at]temporary-mail.online
// 2. Fill signup form
await page.goto('https://yourapp.com/signup');
await page.fill('#email', email);
await page.fill('#password', 'TestPass123!');
await page.click('button[type="submit"]');
// 3. Wait for verification email
await expect(page.locator('.success-message')).toBeVisible();
// 4. Poll for email (or use SSE for real-time)
let messages = [];
for (let i = 0; i < 30; i++) {
const res = await fetch(`https://temporary-mail.online/api/inbox/messages?id=${inbox.id}`);
messages = (await res.json()).messages;
if (messages.length > 0) break;
await new Promise(r => setTimeout(r, 1000)); // wait 1s
}
expect(messages.length).toBeGreaterThan(0);
// 5. Extract verification link
const emailBody = messages[0].body.html;
const verifyLinkMatch = emailBody.match(/href="([^"]*verify[^"]*)"/);
const verifyLink = verifyLinkMatch[1];
// 6. Click verification link
await page.goto(verifyLink);
// 7. Assert user is verified
await expect(page.locator('.verified-badge')).toBeVisible();
});
Use Case 2: Cypress Component Testing
describe('Email Verification Component', () => {
it('should verify email successfully', () => {
cy.request('POST', 'https://temporary-mail.online/api/inbox/create')
.then((response) => {
const email = response.body.email;
cy.visit('/verify');
cy.get('#email').type(email);
cy.get('button').contains('Send Code').click();
// Wait for email
cy.wait(2000);
cy.request(`https://temporary-mail.online/api/inbox/messages?id=${response.body.id}`)
.then((msgResponse) => {
const code = msgResponse.body.messages[0].body.text.match(/\\d{6}/)[0];
cy.get('#code').type(code);
cy.get('button').contains('Verify').click();
cy.contains('Email verified!').should('be.visible');
});
});
});
});
Use Case 3: Jest Unit Testing (Email Service)
describe('EmailService', () => {
it('should send welcome email', async () => {
// Create temp inbox
const inbox = await createTempInbox();
// Trigger email send
await emailService.sendWelcomeEmail(inbox.email);
// Verify email was received
const messages = await waitForEmail(inbox.id, 10000); // 10s timeout
expect(messages).toHaveLength(1);
expect(messages[0].subject).toBe('Welcome to Our App!');
expect(messages[0].body.text).toContain('Thanks for signing up');
});
});
Why Not Use Mailtrap or MailHog?
You might be thinking: "I already use Mailtrap/MailHog for testing. Why switch?"
Mailtrap
Pros: Great for catching emails before they go to production
Cons:
- Mocks the email sending process (doesn't test actual delivery)
- Requires SMTP configuration changes
- Doesn't test your transactional email provider (SendGrid, AWS SES, etc.)
Temporary Mail Online tests the real delivery path. You know that your emails are actually reaching an inbox, not just being caught by a mock server.
MailHog
Pros: Self-hosted, free, open-source
Cons:
- Requires running a separate service (Docker container, etc.)
- No cloud-hosted option
- Limited API features
- Doesn't test external email delivery
Temporary Mail Online is cloud-hosted, requires zero setup, and tests real-world email delivery.
API Pricing & Rate Limits
Free Tier
- 100 inbox creations per day
- 1,000 message retrievals per day
- Perfect for small projects and personal use
Pro Tier ($29/month)
- Unlimited inbox creations
- Unlimited message retrievals
- Priority support
- Webhook support
- Custom domain support (use your own domain for temp emails)
Enterprise
- SLA guarantees
- Dedicated infrastructure
- On-premise deployment options
- Custom integrations
Best Practices for Automated Testing
1. Use Unique Inboxes Per Test
Don't reuse the same inbox across multiple tests. Create a fresh inbox for each test to avoid flaky tests caused by leftover emails.
beforeEach(async () => {
testInbox = await createTempInbox();
});
afterEach(async () => {
// Inbox auto-expires, no cleanup needed
});
2. Set Reasonable Timeouts
Email delivery isn't instant. Set a timeout of 10-30 seconds for email arrival.
const waitForEmail = async (inboxId, timeoutMs = 10000) => {
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
const messages = await getMessages(inboxId);
if (messages.length > 0) return messages;
await new Promise(r => setTimeout(r, 1000));
}
throw new Error('Email not received within timeout');
};
3. Extract Data with Regex
Use regex to extract verification codes, magic links, or other dynamic content.
const extractOTP = (emailBody) => {
const match = emailBody.match(/\\b\\d{6}\\b/); // 6-digit code
return match ? match[0] : null;
};
const extractLink = (emailBody) => {
const match = emailBody.match(/https:\\/\\/yourapp\\.com\\/verify\\?token=[a-zA-Z0-9]+/);
return match ? match[0] : null;
};
4. Test Email Content
Don't just verify that an email arrived—verify its content too.
test('welcome email has correct content', async () => {
const messages = await waitForEmail(inbox.id);
const email = messages[0];
expect(email.subject).toBe('Welcome to Our App!');
expect(email.body.text).toContain('Thanks for signing up');
expect(email.body.html).toContain('<img src="https://yourapp.com/logo.png"');
});
Integration Examples
GitHub Actions CI/CD
name: E2E Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm install
- run: npm run test:e2e
env:
TEMPMAIL_API_KEY: ${{ secrets.TEMPMAIL_API_KEY }}
Docker Compose (Local Development)
version: '3'
services:
app:
build: .
environment:
- TEMPMAIL_API_URL=https://temporary-mail.online/api
test:
build: .
command: npm run test
depends_on:
- app
Conclusion
Manual email testing is a relic of the past. In 2026, modern development teams use APIs to automate everything—including email verification flows.
Temporary Mail Online's Developer API gives you:
- ✅ Instant inbox creation (< 50ms)
- ✅ Real-time message retrieval
- ✅ Parsed JSON responses (no MIME parsing needed)
- ✅ SSE support for long-running tests
- ✅ Tests actual email delivery (not mocked)
Ready to automate your testing workflow?
- Visit temporary-mail.online/developer-api
- Get your API key
- Start testing in minutes
Stop wasting time on manual email verification. Let the API do the work while you focus on building great software.
API Reference
Create Inbox
POST /api/inbox/create
Get Messages
GET /api/inbox/messages?id={inboxId}
Delete Inbox
DELETE /api/inbox/delete?id={inboxId}
Stream Messages (SSE)
GET /api/inbox/sse?id={inboxId}
Full documentation: temporary-mail.online/docs/api
