Mailwurf

Waiting

One open request until the mail is there. No sleeps, no polling loops.

waitFor keeps a single HTTP request open. Mailwurf answers as soon as a matching message is stored, or when the timeout ends.

const mail = await inbox.waitFor({ subject: "Confirm", timeout: 15_000 });

Options

OptionDefaultMeaning
subjectnoneCase-insensitive part of the subject. "confirm" matches "Please Confirm your email".
timeout15000Milliseconds. Maximum 120000. 0 checks once without waiting.
afternoneMessage id. Only messages received after it match.
signalnoneAbortSignal to cancel the wait from the test.

Matching order

The oldest matching message wins. If it is already stored when the wait starts, the call returns immediately. A wait started after the mail arrived does not miss it.

Several emails in one test

Pass the previous message id as after to wait for the next one:

const first = await inbox.waitFor({ subject: "code" });

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

const second = await inbox.waitFor({ subject: "code", after: first.id });
expect(second.otp).not.toBe(first.otp);

Without after, the second call returns first again, because it is still the oldest match. after must be the id of a message in the same inbox; any other value returns 400.

Timeouts

When nothing matches in time, the client throws MailwurfTimeoutError (HTTP 408).

import { MailwurfTimeoutError } from "@mailwurf/e2e";

try {
  await inbox.waitFor({ subject: "Invoice", timeout: 5_000 });
  throw new Error("invoice was sent but should not be");
} catch (error) {
  if (!(error instanceof MailwurfTimeoutError)) throw error;
}

Keep the Mailwurf timeout below the test runner timeout, so the failure names the missing email instead of a generic test timeout.

With timeout: 0 and no match, the call fails with status 404 instead.

Concurrent waits

Each API key can hold four waits open at the same time. A fifth returns 429. With more than four parallel workers, give each CI job its own key or retry the wait after a short pause.

Listing instead of waiting

To assert on everything that has arrived so far, list the messages. The list is newest first.

const messages = await inbox.messages({ subject: "Confirm" });
expect(messages).toHaveLength(1);

On this page