Give email testing agents a bounded inbox and a deterministic check
Pair an agent runner with InboxRhino’s wait-for-message API, then keep token validation in explicit test rules rather than model judgment.
Use a receive-only inbox and a wait-for-message request to verify invoice and account-change emails in WebdriverIO without guessing how long delivery will take.
Transactional email often arrives after the application has finished its visible work. An invoice alert or account-change notice may be queued and delivered a few seconds later, or take longer under CI load. A fixed sleep in a WebdriverIO test guesses at that delay: set it too short and the test flakes; set it too long and every run pays the cost.
A more reliable pattern is to trigger the application action, then ask an inbox API to wait for the expected message. InboxRhino provides receive-only inboxes and an HTTP wait-for-message endpoint that waits up to 180 seconds. The test can wait on mail rather than pausing for an arbitrary interval.
Start by creating an InboxRhino inbox through its API. The service uses real MX addresses that receive mail through Cloudflare. Use the address returned by the create-inbox response as the recipient for the account or transaction under test. Keep the inbox ID for the later message request.
The documented create call uses a bearer API key:
const created = await fetch('https://api.inboxrhino.in/v1/inboxes', { method: 'POST', headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' } }).then((r) => r.json());
InboxRhino’s example response exposes the inbox ID at created.data.id. Use the address supplied by the API when configuring the test user or transaction. Avoid sharing one recipient across parallel cases if the same subject could make a message ambiguous.
In the WebdriverIO test, perform the normal UI action first: for example, request an invoice notification or change an account setting. Then make a REST request for the message. The endpoint accepts a wait duration and can filter by subject or sender. A subject phrase that is stable across test runs is a useful first filter.
const mail = await fetch(`https://api.inboxrhino.in/v1/inboxes/${created.data.id}/messages?wait_seconds=180&limit=1&include=content&subject=${encodeURIComponent('Invoice')}`, { headers: { Authorization: `Bearer ${key}` } }).then((r) => r.json());
This uses the wait-for-message request instead of a timer such as browser.pause(10000). The request waits for a matching message, for up to the specified limit. It does not make email delivery synchronous; it gives the test a bounded wait for an asynchronous event. If the response contains no matching message, treat that as a failed notification check and include the response or relevant test context in the failure output.
First check that a message was returned and that its subject is the expected one. InboxRhino’s example reads the first result as mail.data[0].subject. For a stronger transactional check, include a stable value in the assertion: an invoice number, the account identifier, or the new setting. The endpoint request includes content, and the API returns a parsed body; use the response field documented in the API reference for the body assertion.
Do not make the test depend on incidental presentation details such as whitespace, a full HTML snapshot, or a timestamp that changes on every run. A subject filter helps select the message; a content assertion checks that it belongs to this transaction. If multiple notifications can share a subject, use a sender filter where appropriate and assert a transaction-specific value in the message.
InboxRhino inboxes are receive-only: they cannot send, reply to, or forward email. Messages, headers, and attachments are deleted after 30 days, so the inbox is for test delivery and inspection, not a permanent record. The free tier includes 11 active inboxes and 33 emails per month; account for those limits when choosing how often CI runs this flow.
This approach works for other email checks too: the application action remains a WebdriverIO interaction, while a REST request handles the asynchronous notification. For background on how receiving infrastructure, HTML inspection, and quotas affect test design, see the practical choices behind automated email testing.
Pair an agent runner with InboxRhino’s wait-for-message API, then keep token validation in explicit test rules rather than model judgment.
Comparing specialized receive-only test email APIs like InboxRhino, Tigrmail, and testmail.app for web application QA and CI pipelines.
Small teams can run full integration test suites on free email API tiers by recycling inboxes and targeting specific test flows.