Skip to main content

On This Page

Automating Email Verification Testing in Playwright: Mailpit vs ZeroDrop

3 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

How to test email verification flows in Playwright (Mailpit, MailHog, and a no-setup alternative)

Playwright developers often struggle to automate sign-up and email verification flows in CI environments. Testing these paths requires intercepting real emails to extract and navigate to unique verification links.

Why This Matters

Mocking emails at the API level is sufficient for unit tests but fails to validate the actual delivery path of an application’s communication system.

Key Insights

  • MailHog is an unmaintained fake SMTP server that requires a Docker container in CI environments (Zerodrop, 2026).
  • Local SMTP traps like Mailpit allow developers to intercept emails via HTTP APIs but introduce CI configuration overhead through port mappings and health checks.
  • ZeroDrop provides a no-infrastructure alternative using an npm SDK that replaces manual polling loops with a synchronous waitForLatest method.

Working Examples

Implementing email verification testing using MailHog’s HTTP API.

import { test, expect } from '@playwright/test';

test('email verification flow', async ({ page }) => {
  const testEmail = `test-${Date.now()}@example.com`;
  // Sign up
  await page.goto('/signup');
  await page.fill('[name="email"]', testEmail);
  await page.fill('[name="password"]', 'TestPassword123!');
  await page.click('[type="submit"]');

  // Poll MailHog API for the email
  let verificationUrl: string | null = null;
  for (let i = 0; i < 10; i++) {
    await page.waitForTimeout(1000);
    const res = await fetch('http://localhost:8025/api/v2/messages');
    const data = await res.json();
    const message = data.items?.find((m: any) =>
      m.Content?.Headers?.To?.[0]?.includes(testEmail)
    );
    if (message) {
      const body = message.Content.Body;
      const match = body.match(/https?:\/\/\S+verify\S+/);
      verificationUrl = match?.[0] ?? null;
      break;
    }
  }
  if (!verificationUrl) throw new Error('Verification email not received');

  // Click the verification link
  await page.goto(verificationUrl);
  await expect(page).toHaveURL('/dashboard');
});

Simplified email testing using the ZeroDrop SDK to eliminate manual polling and Docker infrastructure.

import { test, expect } from '@playwright/test';
import { ZeroDrop } from 'zerodrop-client';
test('email verification flow', async ({ page }) => {
  const mail = new ZeroDrop();
  const inbox = mail.generateInbox();
  const testEmail = inbox; // e.g. [email protected]	
avait page.goto('/signup');
avait page.fill('[name="email"]', testEmail);
avait page.fill('[name="password"]', 'TestPassword123!');
avait page.click('[type="submit"]');	
d// Wait for the verification email — no polling loop needed 	// Extract the verification link 	const email = await mail.waitForLatest(inbox, { timeout: 10000 }); 	const match = email.body.match(/https?:\/\/\S+verify\S+/); 	if (!match) throw new Error('No verification link found in email'); 	await page.goto(match[0]); 	await expect(page).toHaveURL('/dashboard'); 	});

Practical Applications

    • Full E2E Sign-up Flow: Using Mailpit within an existing Docker Compose CI pipeline to verify account activation behavior.
    • Zero-Config Testing: Using ZeroDrop for teams without Docker in CI to avoid adding service blocks and port mappings to GitHub Actions workflows.

References:

Continue reading

Next article

How to Monitor Medium Publications and Newsletter Feeds via API

Related Content