All posts
    Guides

    How to Test Email Signup and Account Verification

    The Devmailr Team6 min read

    Email verification is the gate to most products — get it wrong and new users can’t even start. It’s also one of the easiest flows to break and least tested, because verifying the account means reading an email. Here’s how to test signup + verification end-to-end, whether your app uses a code or a link.

    The signup-verification flow

    1. User registers with an email.
    2. App creates an unverified account and emails a verification code or link.
    3. User enters the code (or clicks the link).
    4. App marks the account verified; the user can proceed.

    Set up a disposable inbox

    javascript
    const inbox = await createInbox(`signup-${Date.now()}`)
    await page.goto('https://staging.myapp.com/signup')
    await page.getByLabel('Email').fill(inbox.address)
    await page.getByLabel('Password').fill('correct-horse-battery-staple')
    await page.getByRole('button', { name: 'Sign up' }).click()

    (The createInbox/waitForEmail helpers come from the CI/CD guide.)

    If you verify with a code

    javascript
    const email = await waitForEmail(inbox._id, 'has_code=true')
    await page.getByLabel('Verification code').fill(email.extractedCodes[0])
    await page.getByRole('button', { name: 'Verify' }).click()
    await expect(page.getByText('Welcome')).toBeVisible()
    javascript
    const email = await waitForEmail(inbox._id, 'subject=' + encodeURIComponent('Confirm your email'))
    await page.goto(email.primaryLink)
    await expect(page.getByText('Email confirmed')).toBeVisible()

    Don’t forget the negative cases

    Verification is where real bugs live — assert the negatives too:

    • Unverified users are blocked from the actions verification is meant to gate.
    • A wrong or expired code is rejected with a clear message.
    • The code/link is single-use.
    • Resending verification produces a fresh, working code (and ideally invalidates the old one).

    Bonus: assert the email itself

    Since you have the raw message, assert on it too — that the email is correct, not just that the flow works:

    javascript
    expect(email.from).toContain('noreply@myapp.com')
    expect(email.subject).toMatch(/verify|confirm/i)
    expect(email.verdicts.dkim).toBe('PASS')   // it's authenticated

    That last line checks the email passes DKIM — a quick guard against deliverability regressions. See testing SPF, DKIM, and DMARC for more.

    Related reading

    Try it in two minutes

    Create a disposable prefix@devmailr.app inbox over the API, send mail to it from your app, and read it in your tests. Free plan, no card required.