What is Mailbox Routing?

Mailbox routing uses patterns in email addresses to direct messages to specific handlers or folders. The most common technique is plus-addressing (also called subaddressing), where anything after a '+' in the local part is a tag that can be used for filtering, organization, or identification while delivering to the same mailbox.

How Plus-Addressing Works

Plus-addressing follows the pattern: user+tag@domain.com

- user: The main mailbox identifier

  • +tag: A custom tag for routing/identification
  • @domain.com: The email domain

For example:

  • john+newsletter@example.com
  • john+shopping@example.com
  • john+github@example.com

All deliver to john@example.com, but the tag can be used for filtering.

Mailbox Routing for Testing

In testing, mailbox routing provides powerful benefits:

Test Isolation: Each test uses a unique tag `` signup+test-001@in.plop.email signup+test-002@in.plop.email

Deterministic Fetching: Fetch emails by exact address `` GET /messages?to=signup+test-001@in.plop.email

Parallel Safety: No conflicts between concurrent tests

Context Encoding: Include test metadata in the tag `` signup+ci-run-123-user-456@in.plop.email

plop.email Routing

plop.email uses mailbox+tag routing for deterministic email testing:

- Mailbox: Your team's mailbox identifier

  • Tag: Unique per test/scenario

Example workflow:

  1. Generate unique address: orders+${orderId}@in.plop.email
  2. Use in test: Send order confirmation to that address
  3. Fetch by address: GET /messages/latest?to=orders+12345@in.plop.email
  4. Assert: Verify content matches order

This pattern ensures each test gets exactly the email it triggered.

Example

Using Tags for Test Isolationtypescript
// Each test gets a unique tag
function generateTestEmail(prefix: string): string {
  const uniqueId = crypto.randomUUID();
  return `${prefix}+${uniqueId}@in.plop.email`;
}

// Test 1: Signup flow
test('signup sends welcome email', async () => {
  const email = generateTestEmail('signup');
  await signup(email);
  const message = await plop.getLatest(email);
  expect(message.subject).toContain('Welcome');
});

// Test 2: Password reset (runs in parallel, no conflict)
test('password reset sends link', async () => {
  const email = generateTestEmail('reset');
  await requestReset(email);
  const message = await plop.getLatest(email);
  expect(message.subject).toContain('Reset');
});

Try mailbox routing with plop.email

Get started with reliable email testing in minutes.