Skip to main content

Get Started

@qawolf/emails lets a flow receive and send email through QA Wolf-managed test inboxes. Start with mail.inbox(...).
import { mail } from "@qawolf/emails";

const { emailAddress, waitForMessage } = await mail.inbox({ new: true });

await page.getByLabel("Email").fill(emailAddress);
await page.getByRole("button", { name: "Send magic link" }).click();

const message = await waitForMessage({});

What You Get Back

mail.inbox(...) returns a handle scoped to one address.
const inbox = await mail.inbox({ new: true });

inbox.emailAddress;
await inbox.waitForMessage({});
await inbox.waitForMessages({ minCount: 2 });
await inbox.sendMessage({
  to: ["support@example.com"],
  subject: "Test message",
  text: "Hello from a QA Wolf flow",
});

Use A Unique Address By Default

For most tests, pass new: true.
const inbox = await mail.inbox({ new: true });
That creates a unique derived address so old emails do not affect the current run.

Pin Waiting To The Action

Capture after immediately before the app action that should send email.
const after = new Date();

await page.getByRole("button", { name: "Send code" }).click();

const message = await inbox.waitForMessage({ after });
This prevents the flow from reading a message that arrived earlier.

Runtime Setup

In normal QA Wolf runs, the runner configures the email client. Local harnesses can configure it explicitly.
import { configureEmailsClient, createEmailsClient } from "@qawolf/emails";

const client = await createEmailsClient({
  emailerUrl: process.env["EMAILER_URL"]!,
  pollForEmailsDefaultTimeoutMs: 300_000,
  teamId: process.env["QAWOLF_TEAM_ID"],
  waitForMessagesDefaultDelayMs: 15_000,
});

configureEmailsClient(client);

Next Steps

Last modified on April 24, 2026