OTP email testing
See the tighter product pitch for building OTP assertions with programmable inboxes.
Open pagePlaywright
Use a PostMX temporary inbox to receive a real OTP in the same test that triggered it, without shared mailboxes, brittle waits, or regex scraping.
Make the test wait for the email, not for a mailbox UI.
Why it works
Shared inboxes create collisions, static codes hide regressions, and HTML scraping makes tests brittle. A temporary inbox keeps the verification path isolated, while PostMX gives you the code directly once the next message lands.
The browser test should prove that the app delivered the email and that the OTP arrived. Everything else belongs to the app under test, not to the mailbox plumbing.
Minimal Playwright test
import { test, expect } from "@playwright/test";
import { PostMX } from "postmx";
test("verifies OTP email", async ({ page }) => {
const postmx = new PostMX(process.env.POSTMX_API_KEY!);
const inbox = await postmx.createTemporaryInbox({ label: "playwright-otp" });
await page.goto("http://localhost:3000/login");
await page.getByLabel("Email").fill(inbox.email_address);
await page.getByRole("button", { name: "Send code" }).click();
const message = await postmx.waitForMessage(inbox.id);
expect(message.otp).toBeTruthy();
});
Related links
Use these pages when you need the shorter product overview or the adjacent workflow.
See the tighter product pitch for building OTP assertions with programmable inboxes.
Open pageJump into the broader Playwright-focused page if you want the full workflow context.
Open pageReview the inbox primitive that powers the test flow and the rest of the product surface.
Open pageStart building today
Send the message, wait for it to land, and assert the code your user actually receives.