Use case

Test webhook-triggered email

A lot of your product's email doesn't fire from a button a user just clicked — it fires later, from a webhook or a background job. A payment-succeeded event triggers a receipt, a queue worker sends a notification, a third-party callback raises an alert. That mail arrives out of band, moments to minutes after the thing that caused it. Perenmail gives you a private inbox on a real domain: point the flow at it, trigger the event, and watch the email actually land — live, with the right content, and captured even when it shows up late.

How it works

From event to the email it produced

  1. 01

    Spin up a private inbox on a real domain

    Create a registered-only address in one click. It lives on a real domain, so the mail your app sends in response to the webhook reaches it the same way it would reach a real customer — no special routing to fake.

  2. 02

    Set it as the recipient for the webhook-driven flow

    Point the flow you're testing at the address: the customer record that receives the receipt after a payment-succeeded event, the user a queue worker notifies, or the contact a third-party callback alerts. Wire it in exactly where the real recipient would sit.

  3. 03

    Trigger the webhook or job

    Fire the event the way it happens in production — replay a Stripe or Paddle webhook, enqueue the background job, or hit the endpoint the third party calls back. Then let the async work run on its own schedule.

  4. 04

    The resulting mail lands live

    A listening indicator and poll heartbeat surface the message at the top of the inbox the moment it arrives — no reload, unread state updating in place. You see the out-of-band email land the instant the handler finally sends it.

  5. 05

    Inspect the body, links, and headers

    Read the rendered body in a locked, script-free sandbox, or toggle to Text and Source. Every link is extracted for one-click opening, and the raw RFC822 view with synthesized SPF, DKIM, and DMARC results lets you debug the outbound mail your handler produced.

  6. 06

    The inbox persists, so retries and late fires are all captured

    Inboxes never expire on their own. A webhook the provider retries, a job that runs minutes later, a duplicate send from an at-least-once queue — every attempt is still sitting in the inbox for you to compare, not a test run you have to restart.

Why out-of-band email is easy to miss

The send you didn't watch is the one that breaks

Email that fires inline with a request is easy to verify — you click the button and the mail is right there. Webhook- and job-triggered email is the opposite: the code that sends it runs on someone else's schedule, in a worker you're not watching, sometimes long after you moved on. A handler that silently throws, a queue that drops a task, a template that renders empty — none of it surfaces at the moment you trigger the event, so it's exactly the kind of bug that reaches production untested.

It arrives after you stopped looking

The event fires, the worker picks it up seconds or minutes later, and the email lands when your attention is elsewhere. A persistent inbox with live delivery holds the message at the top until you come back — so a slow send is something you read, not something you assume never happened.

Retries and duplicates pile up

Providers retry webhooks and at-least-once queues re-run jobs, so one event can produce several emails. On an inbox that expires you lose the earlier attempts; here every send stays put, so you can confirm whether your idempotency actually deduplicates the notification.

Because inboxes persist by default and mail streams in live, you replay the webhook, go read your worker logs, and come back to find the resulting email waiting — every attempt of it. This is the same pattern that makes delayed and cron-driven email testable, and it's the foundation for verifying your transactional email end to end.

What you get

The parts that make async email testable

Live delivery

New mail appears at the top the instant it lands, with the unread count updating in place. You never sit refreshing to find out whether the async handler sent anything.

Persistent by default

Inboxes never expire on their own — you keep them until you archive or delete. A message that arrives minutes after you triggered the event is waiting for you, not gone.

Raw source & headers

Full RFC822 view with synthesized SPF, DKIM, and DMARC results, so you can confirm the mail your handler sent is well-formed and authenticated. Raw source, headers & attachments are Personal+.

Not sure which plan you need for raw headers and more inboxes? The pricing page lays out Personal and Personal+, and the FAQ covers how live delivery and persistence work in practice.

Ready when you are

See the email your webhook actually sends.

Create a private inbox on a real domain, point your webhook-driven flow at it, and watch the mail land — retries, delays, and all. Free forever, no credit card.