automated email testing

Run staging email checks in ephemeral Docker environments

Keep staging mail isolated, send verification messages to real test inboxes, and let CI wait for the message instead of guessing at delivery time.

By Ramona Teague·October 29, 2026·4 min read
What matters here
  1. InboxRhino receives test mail but cannot send it; the application still needs an outbound mail transport.
  2. A wait-for-message API call can poll for up to 180 seconds and filter by subject or sender.
  3. Free accounts include 11 active inboxes and 33 inbound emails per month, so parallel tests need quota planning.

Docker makes it easy to start a clean staging environment and just as easy to lose its email when the containers stop. A local SMTP container can capture a message, but it does not tell you whether your application’s configured sender can deliver to an internet-facing mailbox. For a signup or password-reset check, the practical test is whether the message reaches an address your test can inspect.

InboxRhino provides receive-only MX test inboxes on test.inboxrhino.in. The important boundary: it receives messages; it does not send, reply to, or forward them. Your application still needs an outbound mail transport configured for staging. The test inbox is the destination, not an SMTP server for the application.

Separate the staging path from production

Give the containerized application an explicit staging mail configuration. Keep it separate from production credentials and recipients, and pass environment-specific values into the container at startup rather than baking secrets into an image. The recipient for a test run should be the address of an InboxRhino test inbox. Do not use a real customer address as a fallback.

The outbound transport can be whatever your staging system already uses to deliver mail. Configure it to send the verification or reset message to the test address, then verify the resulting message through InboxRhino’s API. This avoids adding a local SMTP capture container just to make the email visible to the test. It does not remove the need for a working sender or prove that a production provider is configured correctly.

For ephemeral Docker environments, create or assign an inbox for the run and make its address available to both the application and test runner. Keep the API key in the runner’s secret store or environment, not in the application image. The application needs the recipient address; the test runner needs the API credential. That split limits how much test infrastructure each container can access.

Make the test wait for the event

Start the application and its dependencies, then trigger the user flow that sends the email. Once the action completes, have the test runner call InboxRhino’s wait-for-message API. It can wait up to 180 seconds and filter by subject or sender. A subject filter such as “Verify” can distinguish the expected message from unrelated mail, but choose a value that is specific enough for your own test traffic.

When the message arrives, assert on the content the user actually needs: a verification code, a reset link, or the expected account detail. Avoid fixed sleeps. A sleep either wastes time when delivery is fast or flakes when it is slow. A bounded wait gives the test a clear failure point without assuming a particular delivery time.

InboxRhino’s documentation includes Playwright integration examples. The same workflow applies to other runners: trigger the application action, poll for the matching message, then assert on its content. Keep the test’s match criteria and expected result explicit. If the wait expires, report which message was expected and which filters were used, rather than silently retrying the whole flow.

Plan for parallelism and cleanup

Parallel Docker jobs should not race to read the same message. Use separate inboxes for concurrent runs where the available quota permits, or otherwise isolate each run’s message with distinctive sender or subject values. The free tier includes 11 active inboxes and 33 inbound emails per month. Those limits can be enough to wire one flow, but they are not an unlimited CI budget. Starter is available with an access code and includes 1,100 active inboxes and 3,300 emails per month. Growth and Scale are planned tiers, not current checkout options.

Track messages per run as well as inboxes. Repeated test retries and broad end-to-end suites can consume inbound email quota faster than expected. Keep the staging suite focused on flows where receiving the actual email matters, and avoid generating extra messages during setup. Messages are retained for 30 days before deletion; do not treat the test inbox as permanent evidence storage.

Inspect the HTML without trusting it

For a failure that looks like a rendering or template issue, open the message in InboxRhino’s sandboxed viewer. It blocks scripts, forms, popups, and remote images, which makes it a safer place to inspect HTML than a normal browser page. That restriction is also a trade-off: remote images will not load, and the viewer is not a complete test of how every mail client renders a message.

This stack is deliberately narrow: Docker supplies a disposable application environment, the staging sender delivers the message, InboxRhino receives it, and the runner checks the result through the API. The trade-off is that a receive-only inbox does not test outbound transport configuration by itself, and quota limits shape how much parallel testing is practical. For a broader discussion of the receiving, inspection, and volume decisions, see how real MX, safe HTML and quotas shape email testing.

More from InboxRhino News