Troubleshooting
The usual reasons a test does not get its email.
Errors from the API
The API key is missing, mistyped, revoked, or expired.
createMailwurf()throws when the key is empty. If the tests passprocess.env.MAILWURF_API_KEY!, check that the variable is set in the process that runs them.- Keys start with
mw_live_. Copy the whole value; it is only shown once. If it is lost, create a new key. - In the dashboard, a revoked key shows Revoked. Expired keys stop working on their expiry date, even though the list still shows them as Active.
- GitHub Actions does not pass secrets to pull requests from forks.
- The inbox is older than one hour and has expired. Create it inside the test, right before the mail is sent.
- The id belongs to another organization. Every key only sees inboxes of its own organization.
- The call used the address instead of the id. Use
inbox.idin API calls; the address is lowercased and does not work as an id.
No matching email arrived before the timeout.
- Remove
subjectand wait again. If a message arrives, the filter did not match; it is a case-insensitive part of the subject, not a pattern. - List everything that arrived:
await inbox.messages(). - If nothing arrived, the app did not deliver it. Check the provider's logs for the recipient address. See The app must send real mail.
- Raise
timeout(up to120000) for slow providers, and the test runner timeout above it.
One API key holds more than four waits at once. Lower the worker count or split parallel jobs across several keys. See Waiting.
after is not the id of a message in this inbox. Pass the id of a message returned for the same inbox.
The organization sent more than 60 messages in the last minute. Wait a moment, or send fewer messages per test. See Sending.
The send went to an address on the Mailwurf mail domain that is not an active inbox. Create the recipient inbox first, and send before it expires.
createInbox() does not accept an address. Temporary addresses are always generated. For a fixed address, register a permanent address in the dashboard.
API keys cannot delete permanent addresses. Delete them in the dashboard under Inboxes.
Sending over SMTP
The password is not a valid API key. Use the whole key (mw_live_…) as the password; the username can be mailwurf. A revoked or expired key is refused too.
The From address of the mail must be one of your inboxes. Many apps have their own setting for the sender address; set it to the address you registered, for example billing@acme.com.
The organization sent more than 60 mails in the last minute. Each recipient of a mail counts as one. The app should try again a minute later.
Use port 465 with TLS (some apps call it SSL), or port 587 with STARTTLS. Hosting providers sometimes block outgoing mail ports; if one port does not connect, try the other.
See Send over SMTP for all answers of the server.
Mail was sent but never arrived
Mailwurf only accepts mail for inboxes that exist and have not expired. Check that the recipient is exactly inbox.address, and that the test did not reuse an address from an earlier run.
The email is larger than 5 MiB, usually because of attachments. Send a smaller variant in test environments.
- Sandbox or test modes of mail providers often deliver only to verified addresses.
- A local fake SMTP server or mail catcher is still configured for the app.
- A suppression list at the provider blocks the recipient after earlier bounces.
The message looks wrong
links lists every URL in order, starting with logos and header links. Find the link by its path. See Links.
HTML entities in links are not decoded. Use url.replaceAll("&", "&") before opening it.
otp finds 4–8 character codes (digits, or uppercase letters with digits) after words like "code", a standalone 6-digit number, or a 6-character code on its own line. Codes with spaces, dashes, or lowercase letters are not detected, and an unrelated number near a label word can be picked up. Read the code from mail.text instead. See One-time codes.
from is the return address of the sending server, which many providers set to a bounce address. Assert on the subject or body instead.
Open the inbox in the dashboard. Under Sent, the message shows the reason delivery failed. Mail the receiving server rejects outright is not retried.
Wait returns the oldest match. Pass after: previous.id to get the next one. See Several emails in one test.
Package errors
@mailwurf/e2e is ESM-only. Use import, set "type": "module", or use a .mjs / .mts file.
The package calls https://api.mailwurf.io and reads no environment variables. Only the apiUrl option of createMailwurf() changes the origin.
Mailwurf