MailToYou

Temporary Email for Developers: Testing Registration Flows, Webhooks, and Transactional Email

10 min read
developer toolstestingemail testingQAtemporary email APIwebhook testing

If you build software that sends email — registration confirmations, password resets, order receipts, team invitations — you know the testing pain. You need a fresh email address for every test run. Gmail aliases fill up fast. Shared test accounts cause collisions between team members. Internal mail servers need DevOps time to configure and maintain.

Temporary email services solve this by providing unlimited fresh inboxes that require zero configuration. MailToYou goes further by offering a REST API that lets you automate the entire cycle: create an address, trigger a registration, poll for the verification email, extract the code, and confirm the account — all in a single CI script.

This article covers practical patterns for using temporary email in software development, from manual QA testing to fully automated integration pipelines.

The problem with testing email in development

Every developer eventually faces these email testing headaches:

Unique address requirements. Most registration systems reject duplicate email addresses. Testing a sign-up flow ten times means you need ten different email addresses. Creating ten Gmail accounts is tedious and rate-limited. Plus-addressing (yourname+test1@gmail.com) works on some platforms but gets detected as a duplicate by others.

Shared test environments. When three developers test the same staging system, they use the same test email addresses and step on each other's toes. Dev A triggers a password reset, but Dev B's test checks the inbox and picks up the wrong email.

Email delivery latency. Some email providers introduce delays of 30 seconds to several minutes for incoming mail. When you are testing a flow that requires a verification code, waiting for email delivery breaks your concentration and slows iteration.

Transactional email preview. You want to see exactly what the user sees — the rendered HTML, the subject line, the from address — not a log entry in your console. Catching layout bugs in email templates requires viewing the actual delivered message.

Cleanup burden. Test inboxes accumulate hundreds of messages. Someone has to clean them up periodically, or the test environment becomes unusable. With temporary email, cleanup is automatic.

Manual QA testing with MailToYou

For quick manual testing during development, the browser-based workflow is straightforward:

Testing a registration flow

  1. Open MailToYou and generate a random address (or use a custom one like testuser@m2u.io)
  2. Open your application's registration page in another browser tab
  3. Enter the temporary address and complete the registration form
  4. Switch back to the MailToYou tab — the verification email appears in real time via SSE
  5. Click the email, copy the verification code or click the verification link
  6. Complete the registration in your application

The real-time inbox delivery means you do not need to refresh or poll. The email shows up the moment your application sends it.

Testing password reset flows

  1. Register an account using a temporary address (see above)
  2. Navigate to the "Forgot Password" screen
  3. Enter the same temporary address
  4. The password reset email arrives instantly in MailToYou
  5. Click the reset link and verify the flow completes correctly

Since MailToYou addresses last seven days, you can test multi-step flows that span days: register on Monday, reset password on Wednesday, verify account recovery on Friday.

Testing email templates across devices

When you need to verify that your HTML email renders correctly:

  1. Send a test email to a MailToYou address
  2. Open MailToYou on your desktop browser — check the desktop rendering
  3. Open the same inbox on your phone's browser — check the mobile rendering
  4. Compare subject lines, from addresses, and reply-to headers

MailToYou renders the email HTML safely in an isolated container, so you see the same content your users would see in their actual email clients.

Automated testing with the MailToYou API

The real power for developers comes from the API. You can programmatically create inboxes, check for messages, and extract content — making temporary email a first-class component of your test suite.

API basics

MailToYou exposes a REST API at your configured API endpoint. The key endpoints:

POST /v1/mailboxes/auto         → Create a random mailbox
POST /v1/mailboxes/custom       → Create a custom address
GET  /v1/mailboxes/:token/messages?view=:viewToken  → List messages
GET  /v1/mailboxes/:token/messages/:id?view=:viewToken → Get single message
GET  /v1/domains                → List available domains

Pattern 1: Automated registration test

Here is a practical example using Node.js and your test framework of choice:

// test/registration.test.js
import { describe, it, expect } from 'vitest';

const API_BASE = process.env.MAIL_API_URL || 'https://api.m2u.io';
const APP_URL = process.env.APP_URL || 'http://localhost:3000';

async function createMailbox() {
  const res = await fetch(`${API_BASE}/v1/mailboxes/auto`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
  });
  return res.json(); // { address, token, view_token, ... }
}

async function waitForEmail(token, viewToken, maxWait = 15000) {
  const start = Date.now();
  while (Date.now() - start < maxWait) {
    const res = await fetch(
      `${API_BASE}/v1/mailboxes/${token}/messages?view=${viewToken}`
    );
    const data = await res.json();
    if (data.messages && data.messages.length > 0) {
      return data.messages[0];
    }
    await new Promise(r => setTimeout(r, 1000));
  }
  throw new Error('Timed out waiting for email');
}

describe('User Registration', () => {
  it('should send verification email after signup', async () => {
    // 1. Create fresh mailbox
    const mailbox = await createMailbox();

    // 2. Register with the temp address
    const signupRes = await fetch(`${APP_URL}/api/auth/register`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: mailbox.address,
        password: 'TestPass123!',
        name: 'Test User',
      }),
    });
    expect(signupRes.status).toBe(201);

    // 3. Wait for verification email
    const email = await waitForEmail(mailbox.token, mailbox.view_token);
    expect(email.subject).toContain('Verify');

    // 4. Extract verification code or link
    const codeMatch = email.body.match(/\b(\d{6})\b/);
    expect(codeMatch).not.toBeNull();

    // 5. Verify the account
    const verifyRes = await fetch(`${APP_URL}/api/auth/verify`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: mailbox.address,
        code: codeMatch[1],
      }),
    });
    expect(verifyRes.status).toBe(200);
  });
});

Every test run gets a unique email address. No cleanup needed. No race conditions between parallel tests.

Pattern 2: Testing webhook email notifications

If your application sends emails in response to webhook events (Stripe payment received, GitHub push, Slack notification), you can use temporary email to verify the entire pipeline:

async function testWebhookEmailNotification() {
  // Create a mailbox for the test user
  const mailbox = await createMailbox();

  // Set up a user in your system with this temp email
  await setupTestUser({ email: mailbox.address });

  // Simulate a webhook event (e.g., Stripe payment succeeded)
  await fetch(`${APP_URL}/api/webhooks/stripe`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Stripe-Signature': generateTestSignature(payload),
    },
    body: JSON.stringify({
      type: 'payment_intent.succeeded',
      data: {
        object: {
          amount: 2999,
          currency: 'usd',
          receipt_email: mailbox.address,
        },
      },
    }),
  });

  // Verify the notification email was sent
  const email = await waitForEmail(mailbox.token, mailbox.view_token);
  expect(email.subject).toContain('Payment');
  expect(email.body).toContain('$29.99');
}

Pattern 3: Parallel test execution with isolated mailboxes

One of the biggest advantages of temporary email in CI environments is test isolation. Each test creates its own mailbox, so parallel test execution never causes conflicts:

// Run 10 registration tests in parallel — each gets its own address
const results = await Promise.all(
  Array.from({ length: 10 }, async (_, i) => {
    const mailbox = await createMailbox();
    const res = await registerUser(mailbox.address, `user${i}`);
    const email = await waitForEmail(mailbox.token, mailbox.view_token);
    return { address: mailbox.address, registered: res.ok, emailReceived: !!email };
  })
);

// All 10 tests run independently with zero collision risk
results.forEach(r => expect(r.registered && r.emailReceived).toBe(true));

Pattern 4: Email template regression testing

Catch visual regressions in your email templates by comparing the rendered HTML against a baseline:

async function testEmailTemplateRendering() {
  const mailbox = await createMailbox();

  // Trigger the email you want to test
  await triggerWelcomeEmail(mailbox.address);

  const email = await waitForEmail(mailbox.token, mailbox.view_token);

  // Check structural elements
  expect(email.html).toContain('<!DOCTYPE html>');
  expect(email.html).toContain('<img'); // Logo image
  expect(email.html).toContain('font-family'); // CSS styles

  // Check content
  expect(email.html).toContain('Welcome');
  expect(email.html).not.toContain('{{name}}'); // No unrendered template variables
  expect(email.html).not.toContain('undefined');
}

CI/CD integration patterns

GitHub Actions example

name: Email Integration Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci

      - name: Start application
        run: npm run dev &
        env:
          DATABASE_URL: ${{ secrets.TEST_DB_URL }}

      - name: Run email integration tests
        run: npm run test:email
        env:
          MAIL_API_URL: https://api.m2u.io
          APP_URL: http://localhost:3000

Docker Compose for local testing

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - MAIL_API_URL=https://api.m2u.io

  test-runner:
    build:
      context: .
      dockerfile: Dockerfile.test
    depends_on:
      - app
    environment:
      - APP_URL=http://app:3000
      - MAIL_API_URL=https://api.m2u.io
    command: npm run test:email

Comparing email testing approaches

Approach Setup Time Cost Isolation Real Delivery Automation
MailToYou temp email None Free Full (unique per test) Yes REST API
Gmail + plus addressing Minutes Free Partial (shared base) Yes Limited
Mailtrap 10 min Freemium Per-inbox Simulated API
MailHog (local) 15 min + Docker Free Per-instance Local only API
AWS SES sandbox 30 min + IAM Pay per email Per-sender Yes AWS SDK
Dedicated test SMTP Hours Server cost Shared Yes Custom

MailToYou's advantages for developers:

  • Zero infrastructure to maintain
  • Real internet email delivery (tests the full SMTP path, not just API calls)
  • Automatic cleanup (no test mailbox grooming)
  • SSE-based real-time delivery (tests resolve faster)
  • Multiple domains (test domain-specific logic)

Tips for developer workflows

Use custom addresses for debugging. When you are debugging a specific flow, use a descriptive address like debug-checkout@m2u.io so you can easily identify the relevant inbox in the MailToYou UI.

Set reasonable polling timeouts. Most emails from your own application should arrive within 2-5 seconds via MailToYou. Set your test timeout to 15-30 seconds to account for slow CI runners, but investigate if it consistently takes longer — that might indicate a performance issue in your email sending code.

Test with multiple domains. If your application behaves differently based on the email domain (corporate vs. personal vs. educational), use MailToYou's domain options to test each path. The edu.kg domain is particularly useful for testing education-specific features.

Extract structured data from emails. Instead of matching raw HTML strings, parse the email body to extract specific data points:

function extractVerificationCode(emailBody) {
  // Match 6-digit codes, OTP patterns, or verification links
  const codeMatch = emailBody.match(/\b(\d{4,6})\b/);
  const linkMatch = emailBody.match(/https?:\/\/[^\s"]+verify[^\s"]*/i);
  return { code: codeMatch?.[1], link: linkMatch?.[0] };
}

Log mailbox details on test failure. When an email test fails, log the mailbox address and token so you can manually inspect the inbox in the browser:

try {
  const email = await waitForEmail(mailbox.token, mailbox.view_token);
} catch (e) {
  console.error(`Test failed. Inspect inbox: https://m2u.io — address: ${mailbox.address}`);
  throw e;
}

Security notes for development use

Never use temporary email for production account recovery. Development and testing accounts should use temporary addresses. Production admin accounts and service accounts should use permanent, controlled email addresses.

Do not hardcode API tokens in tests. Even though MailToYou does not require authentication for basic use, treat mailbox tokens as ephemeral secrets. Do not commit them to version control or log them in production CI output.

Be aware of rate limits. If you are creating hundreds of mailboxes per minute in an automated pipeline, be respectful of the service's rate limits. Batch your tests or introduce minimal delays between mailbox creation calls.

Wrapping up

Temporary email fits naturally into the developer workflow anywhere email verification or notification is involved. MailToYou's API turns what used to be a manual, error-prone process — creating test inboxes, checking for emails, cleaning up — into a couple of HTTP calls that slot cleanly into existing test frameworks.

The combination of zero-setup, real email delivery, automatic expiration, and API access makes it particularly useful for:

  • Registration and onboarding flow testing
  • Webhook notification verification
  • Email template regression testing
  • CI/CD pipeline integration
  • Parallel test execution with full isolation

Your tests get unique addresses, your inboxes clean themselves up, and your CI pipeline does not need a mail server.