<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Andrew's Blog]]></title><description><![CDATA[Andrew's Blog]]></description><link>https://goji-andrew.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 25 Oct 2026 12:16:29 GMT</lastBuildDate><atom:link href="https://goji-andrew.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Testing Signup and Email Verification Flows with Disposable Inboxes]]></title><description><![CDATA[A practical checklist for QA-ing signup, verification and password-reset emails using throwaway inboxes, plus the edge cases most teams miss.]]></description><link>https://goji-andrew.hashnode.dev/testing-signup-and-email-verification-flows-with-disposable-inboxes</link><guid isPermaLink="true">https://goji-andrew.hashnode.dev/testing-signup-and-email-verification-flows-with-disposable-inboxes</guid><category><![CDATA[Testing]]></category><category><![CDATA[webdev]]></category><category><![CDATA[email]]></category><category><![CDATA[QA]]></category><dc:creator><![CDATA[Andrew]]></dc:creator><pubDate>Thu, 22 Oct 2026 17:32:29 GMT</pubDate><content:encoded><![CDATA[<p><em>Disclosure: I run <a href="https://temp-mail.agency">temp-mail.agency</a>, one of the disposable inbox services mentioned below. This article was written with AI assistance and reviewed by me for accuracy.</em></p>
<p>Almost every product has an email-gated flow: sign up, confirm your address, reset your password, accept an invite. These flows break quietly. A template variable renders as <code>{{name}}</code>, a link points at staging, or a token expires before the email even lands. Nobody notices until a real user complains.</p>
<p>Testing these flows by hand with your personal Gmail doesn't scale. You run out of <code>+alias</code> variations, your inbox fills with test noise, and some apps strip or reject plus-addressing anyway. Disposable inboxes fix most of that. Here's how I use them, and where they fall short.</p>
<h2>Why a disposable inbox helps in testing</h2>
<p>A disposable (temporary) inbox is a receive-only address you can create in seconds without registering. For QA that gives you three things:</p>
<ol>
<li><strong>A fresh identity per test run.</strong> Each run starts with a brand-new address, so you're testing the real "new user" path rather than a half-migrated account.</li>
<li><strong>No pollution of real inboxes.</strong> Verification codes, welcome sequences and digest emails land somewhere you can throw away.</li>
<li><strong>A realistic view of what the user sees.</strong> You read the rendered email as a recipient would, not just a log line saying "email queued."</li>
</ol>
<h2>A checklist for email-gated flows</h2>
<p>Run through this for each flow (signup, reset, invite, email change):</p>
<p><strong>Delivery</strong></p>
<ul>
<li>Does the email arrive at all? How long does it take? Write down the typical delay so you can spot regressions.</li>
<li>Is the sender name and <code>From</code> address what you expect, or does it still say <code>noreply@localhost</code>?</li>
<li>Is the subject line meaningful when it's sitting in a list of 30 other emails?</li>
</ul>
<p><strong>Content</strong></p>
<ul>
<li>Do all template variables render? Search the body for <code>{{</code>, <code>%s</code>, <code>undefined</code> and <code>null</code>.</li>
<li>Do links point to the right environment? A production email that links to <code>staging.</code> is a classic.</li>
<li>Is there a plain-text alternative, and is it readable?</li>
</ul>
<p><strong>Tokens and links</strong></p>
<ul>
<li>Click the verification link twice. The second click should fail gracefully, not with a 500.</li>
<li>Wait past the token expiry window and click again. Is the "link expired" page helpful, and does it offer a resend?</li>
<li>Request two codes in a row. Does the first one still work? It shouldn't, if your design says only the latest is valid.</li>
<li>Open the link in a different browser from the one that started the signup. Does the flow still complete?</li>
</ul>
<p><strong>Abuse and edge cases</strong></p>
<ul>
<li>Hit "resend" ten times quickly. Is there rate limiting? Does the UI tell the user?</li>
<li>Sign up twice with the same address. Do you leak whether an account exists?</li>
<li>Try an address with uppercase letters. Is it normalised consistently between signup and login?</li>
</ul>
<h2>Automating it</h2>
<p>Clicking through by hand is fine for exploratory testing, but for regression tests you want an inbox you can poll from code. Several disposable inbox services expose a simple HTTP API for this. The pattern is usually:</p>
<ol>
<li>Create an inbox (or a session) and get back an address plus an ID.</li>
<li>Use that address in your end-to-end test (Playwright, Cypress, etc.) to fill in the signup form.</li>
<li>Poll the inbox's messages endpoint until an email arrives or a timeout passes.</li>
<li>Parse the code or link out of the body and continue the test.</li>
</ol>
<p>A rough sketch in pseudo-JavaScript:</p>
<pre><code class="language-js">const inbox = await createInbox();          // returns { id, address }
await page.fill('#email', inbox.address);
await page.click('button[type=submit]');

const msg = await pollUntil(() =&gt; listMessages(inbox.id), {
  timeoutMs: 60_000,
  intervalMs: 3_000,
});
const link = msg.body.match(/https:\/\/\S+\/verify\S+/)[0];
await page.goto(link);
await expect(page.getByText('Email confirmed')).toBeVisible();
</code></pre>
<p>Keep the timeout generous. Email delivery is not instant, and a flaky 10-second timeout will train your team to ignore failures.</p>
<p>For reference, temp-mail.agency has a free API that follows this shape: you create a client session, optionally list the available domains and create a custom address, then fetch messages for that address. The endpoints and parameters are on its <a href="https://temp-mail.agency/api">API page</a>. Other services work similarly, so pick whichever fits your stack.</p>
<h2>Limitations you should know about</h2>
<p>Disposable inboxes are a testing and privacy tool, not a replacement for real email infrastructure:</p>
<ul>
<li><strong>Some senders block them.</strong> Many services keep blocklists of known temporary domains. If your own product blocks them, you'll need an allowlist for your test domain or a different approach (a catch-all domain you control, or a local SMTP sink like Mailpit for pre-production).</li>
<li><strong>They're receive-only.</strong> You can't test reply-to flows or inbound email processing with them.</li>
<li><strong>They're not private by default.</strong> Treat anything sent to a public disposable inbox as visible to others. Never use real customer data, real passwords, or production secrets in these tests.</li>
<li><strong>Respect other sites' terms.</strong> Use them for your own products and for permitted signups, not for dodging limits on services that forbid it.</li>
</ul>
<p>For local and CI environments, an SMTP sink you run yourself is often the better choice. Disposable inboxes shine when you need to test against your <em>real</em> production mail provider, since they show you deliverability problems a local sink would never catch.</p>
<h2>Wrapping up</h2>
<p>Email flows deserve the same test coverage as your API. A short checklist, a fresh inbox per run, and an automated polling step will catch most of the embarrassing bugs before users do.</p>
<p>What edge cases have bitten you in signup or reset flows? I'd like to add them to the checklist.</p>
<p><em>Disclosure, again: I run temp-mail.agency. It's free and receive-only, and I've tried to keep this guide useful whichever inbox tool you use.</em></p>
]]></content:encoded></item></channel></rss>