View all services
Talk to QA Advisor
Browse the Knowledge Hub56 resources
/Test Cases/Email verification test cases

Test cases

Email verification test cases, past did the mail arrive

Twenty eight cases covering token reuse and expiry, invalidating earlier links on reissue, rate limiting and account enumeration, address normalisation and header injection, safe address change, mail scanner prefetching, client rewriting, bounce handling and open redirects.

28cases/8coverage types/13security cases/FreeCSV download

All 28 test cases, ready to copy

Free to use and adapt, no sign-up. Download as CSV or Markdown, or copy it straight into your own tooling.

Last updated

28 worked examples

VER-01

Verify an address using a valid link

TypeFunctionalPriorityHigh
Test data
A newly registered address opening its verification link once
Expected result
Address is marked verified, the user is signed in or directed to sign in per policy, and the confirmation states which address was verified.
VER-02

Refuse a token that has already been used

TypeSecurityPriorityHigh
Test data
Open the same verification link twice
Expected result
Second attempt is refused or reports the address as already verified, and the token cannot be reused to verify a different pending change.
VER-03

Refuse an expired token

TypeBoundaryPriorityHigh
Test data
A token one minute before expiry and one minute after
Expected result
Accepted then refused, with an offer to send a new link. A token with no expiry stays valid in an old inbox indefinitely.
VER-04

Refuse a forged or altered token

TypeSecurityPriorityHigh
Test data
A token with one character changed, a truncated token, and one generated for another account
Expected result
All refused with the same generic message, and tokens are long, random and unguessable rather than derived from the address or a sequential identifier.
VER-05

Invalidate the previous token when a new one is issued

TypeStatePriorityHigh
Test data
Request the link three times, then open the first link
Expected result
Only the newest token works. Leaving earlier tokens valid multiplies the window in which any one of them can be intercepted.
VER-06

Rate limit verification email requests

TypeSecurityPriorityHigh
Test data
Request the link ten times in a minute for one address
Expected result
Requests are throttled with a clear message. An unthrottled endpoint is a mail bombing tool aimed at any address an attacker chooses.
VER-07

Reveal nothing about whether an address is registered

TypeSecurityPriorityHigh
Test data
Request verification for a registered address and an unregistered one
Expected result
Identical response, identical wording and comparable timing, so the endpoint cannot be used to enumerate which addresses hold accounts.
VER-08

Restrict what an unverified account can do

TypeSecurityPriorityHigh
Test data
An unverified account attempting a restricted action through the interface and directly through the API
Expected result
Refused on both paths. A restriction enforced only by hiding controls is bypassed by anyone who sends the request directly.
VER-09

Handle registration on an address that already exists

TypeSecurityPriorityHigh
Test data
Register with an address that already has a verified account
Expected result
No account is created or overwritten, the response does not confirm the address is taken, and the existing owner is notified of the attempt.
VER-10

Normalise addresses consistently

TypeNegativePriorityHigh
Test data
Mixed case in the local part and domain, surrounding whitespace, and a trailing dot on the domain
Expected result
Domain comparison is case insensitive and whitespace is trimmed, and the same normalisation is applied at registration, verification and sign in so all three agree.
VER-11

Apply a documented rule to aliases and subaddresses

TypeBoundaryPriorityMedium
Test data
A plus suffix alias and a dotted variant of an existing address
Expected result
Treated according to a stated rule and applied identically everywhere. An inconsistent rule allows duplicate accounts or blocks legitimate ones.
VER-12

Reject malformed and hostile address values

TypeNegativePriorityHigh
Test data
Missing at sign, two at signs, a leading dot, an address at maximum length, one over it, and one containing a newline
Expected result
Each refused. The newline case matters most, because an unfiltered newline allows header injection into the outgoing message.
VER-13

Accept an internationalised address

TypeCompatibilityPriorityMedium
Test data
A unicode domain and a unicode local part
Expected result
Accepted or refused according to a documented decision, and if accepted the address is stored, displayed and delivered to consistently.
VER-14

Verify a change of address without releasing the old one early

TypeStatePriorityHigh
Test data
Request a change to a new address, then check the account before the new address is verified
Expected result
Old address remains active and in use until the new one is verified, so a mistyped new address cannot lock the user out.
VER-15

Notify the old address when a change is requested

TypeSecurityPriorityHigh
Test data
Request an address change on an account
Expected result
Old address receives a notification with a route to reverse the change, which is the control that surfaces an account takeover in progress.
VER-16

Cancel a pending address change

TypeStatePriorityMedium
Test data
Request a change, cancel it, then open the verification link
Expected result
Link is refused and the account keeps the original address, with no pending state left behind.
VER-17

Handle two pending changes requested in sequence

TypeBoundaryPriorityMedium
Test data
Request a change to one address, then to a second, then open the first link
Expected result
Only the most recent request is valid, and the superseded link is refused rather than reverting to an address the user abandoned.
VER-18

Require the current session or password to change the address

TypeSecurityPriorityHigh
Test data
Attempt the change with a long lived session and after re-authentication
Expected result
Re-authentication is required, because changing the address on an unattended session is the first move in taking over an account.
VER-19

Verify with a code instead of a link

TypeFunctionalPriorityMedium
Test data
A correct code, an expired code, and repeated wrong codes
Expected result
Correct code verifies, expired is refused, and wrong attempts are limited so the code space cannot be brute forced.
VER-20

Handle the link being opened in a different browser

TypeStatePriorityHigh
Test data
Register in one browser and open the link in another with no session
Expected result
Verification still completes. Requiring the original session fails for every user whose mail client opens links in its own browser.
VER-21

Survive a mail client prefetching the link

TypeSecurityPriorityHigh
Test data
A scanner or client issuing a GET on the link before the user clicks it
Expected result
A prefetch does not consume the token silently, or the flow requires a confirming action, so the user does not arrive to find the link already used.
VER-22

Keep the link intact through mail client rewriting

TypeCompatibilityPriorityMedium
Test data
A link passed through a scanner that rewrites URLs, and one wrapped across lines by a plain text client
Expected result
Link still resolves. Tokens are URL safe and short enough not to be broken by line wrapping.
VER-23

Send a message that renders and delivers correctly

TypeCompatibilityPriorityHigh
Test data
The message viewed in a desktop client, a mobile client, a webmail client and as plain text
Expected result
Link is visible and clickable in all four, a plain text alternative exists, and authentication records are configured so the message is not filed as spam.
VER-24

Handle a hard bounce from the address

TypeNegativePriorityHigh
Test data
Register with a valid syntax address on a domain that rejects it
Expected result
Bounce is recorded, the user is shown a route to correct the address, and repeated sending to a hard bouncing address is stopped.
VER-25

Behave correctly when the mail provider is unavailable

TypeStatePriorityHigh
Test data
Make the outbound mail service fail during registration
Expected result
Account creation either completes with a retry queued or fails cleanly, and the user is told which. A silent failure leaves an unverifiable account.
VER-26

Redirect to the intended destination after verifying

TypeSecurityPriorityHigh
Test data
A return path pointing at an internal page, then at an external host
Expected result
Internal path is honoured and the external one refused, so the verification link cannot be turned into an open redirect.
VER-27

Leak no personal data in the link or its landing page

TypeSecurityPriorityHigh
Test data
Inspect the link, the landing page and any analytics or referrer traffic it generates
Expected result
No address or token is exposed to a third party script or sent in a referrer header, and the token is not written to a server access log in a recoverable form.
VER-28

Complete verification with a keyboard and a screen reader

TypeAccessibilityPriorityMedium
Test data
Keyboard only navigation on the pending screen, the resend control and the code entry field
Expected result
Pending state is announced, the resend control is reachable and reports its result, and the outcome of verification is announced rather than only shown.

What goes in each field

ID

Required

Stable identifier, prefixed by module.

Test case

Required

What is being verified, in one line.

Type

Functional, negative, boundary, security, state, performance, accessibility or compatibility. Use it to check coverage is spread rather than clustered on the happy path.

Priority

Risk based. Anything that verifies an address the user does not control, allows a reusable or non expiring token, or reveals whether an address is registered is High.

Test data

The specific values, including the invalid and boundary ones.

Expected result

Required

The precise observable outcome, including message text where the wording itself is the requirement.

How To Use This

Request the link three times

Confirming the message arrives is where most test sets stop. These four conditions are where verification stops proving anything.

Reissue, then use the oldest link

Request the link three times and open the first one. If earlier tokens stay valid, every reissue widens the window in which one of them can be intercepted.

Compare registered and unregistered

Request verification for an address that has an account and one that does not. Different wording, or a noticeably different response time, turns the endpoint into an enumeration tool.

Let a scanner touch the link first

Corporate mail scanners issue a GET on every link before the user sees it. A token consumed by that request means the real user arrives to find their link already used.

Put a newline in the address

An unfiltered newline in an address field is header injection into the outgoing message. It is one input and it turns your mail server into someone else relay.

What Most Sets Miss

Why verification stops proving ownership

Verification exists to prove that somebody controls an address, and the token lifecycle is what makes that proof meaningful. A token that can be used twice, that never expires, or that stays valid after a newer one is issued does not prove present control: it proves someone had access to that inbox at some point, possibly years ago on a shared or recycled address. Single use, short lived, and invalidated on reissue are three separate cases and all three are commonly missing.

The enumeration case is the one teams argue about and should not. If requesting verification for a registered address produces different wording, a different status, or a measurably different response time than an unregistered one, the endpoint tells an attacker which addresses hold accounts. That list has value on its own and it is the first step in a credential stuffing campaign. The same applies to registration: attempting to register an address that already exists must not confirm that it exists, and the existing owner should be told that somebody tried.

Mail infrastructure introduces failures that have nothing to do with the application logic. Corporate scanners prefetch links, so a token consumed by an automated GET leaves the genuine user with a dead link and no idea why. Clients rewrite URLs and wrap plain text at fixed widths, which breaks tokens that are too long or not URL safe. And the link will frequently be opened in a different browser from the one used to register, because mail clients open links in their own, so any flow that requires the original session fails for a large share of real users.

Finally, the address change flow is a takeover path and needs its own care. The old address has to stay active until the new one is verified, otherwise a typo locks the user out permanently. The old address has to be notified of the request, because that notification is what surfaces a takeover in progress. Re-authentication has to be required, because changing the address is the first move an attacker makes on an unattended session. And the verification link needs its redirect target validated, or it becomes an open redirect wearing a trusted domain.

Suggest an improvement

Testing registration and account flows?

QAble tests account lifecycle end to end, including token handling, enumeration resistance, mail deliverability and the address change path.

Functional testing services

More test case sets

View all

Test cases for a login page

Test cases
25 cases across functional, negative, boundary, security, session and accessibility paths, including account enumeration and lockout.

Test cases for a registration form

Test cases
28 cases covering validation, duplicate accounts, email verification, password rules and the enumeration leak most signup forms ship with.

Test cases for search functionality

Test cases
28 cases across relevance, partial and fuzzy matching, filters, pagination, empty states, injection attempts and performance under load.

Test cases for a shopping cart

Test cases
27 cases on quantity limits, price recalculation, stock changes, coupon stacking, guest to account merge and cart persistence.

Test cases for checkout and payment

Test cases
30 cases including 3D Secure, declines, timeouts, duplicate charges, idempotency, refunds and partial captures.

Test cases for file upload

Test cases
28 cases on size and type limits, spoofed content types, malicious filenames, progress, resume, virus scanning and storage limits.

Test cases for forgot password

Test cases
26 cases on reset token expiry, single use enforcement, session invalidation and the enumeration and rate limit gaps that are routine here.

Test cases for OTP verification

Test cases
26 cases on expiry, resend throttling, attempt limits, code reuse, delivery failure and the brute force window teams forget to close.

Test cases for user roles and permissions

Test cases
26 cases on horizontal and vertical privilege checks, direct object access, role changes mid-session and permission inheritance.

Test cases for form validation

Test cases
27 rules-based cases on required fields, length and numeric boundaries, client and server parity, hidden field tampering and error accessibility.

Test cases for a date picker

Test cases
26 cases on timezone shifts, ambiguous day and month order, impossible dates, min and max limits, leap years and keyboard operation.

Test cases for pagination

Test cases
24 cases on ordering stability, records changing mid-session, page size caps, deep offset cost, permission-filtered totals and state restore.

Test cases for push notifications

Test cases
26 cases on app states, deep link routing, token release on sign out, lock screen privacy, preferences, provider failures and platform differences.

Test cases for reports and data export

Test cases
25 cases on permission filtering in the file, spreadsheet formula injection, encoding, typed numbers and dates, row limits and audit logging.

Test cases for a chatbot

Test cases
28 cases on paraphrased intents, context, fallback loops, human handoff, policy grounding, prompt injection and data scoping.

Test cases for net banking transactions

Test cases
28 cases on duplicate debits from a retried request, concurrent transfers against one balance, daily limits across channels, beneficiary cooling periods, second factor binding and reconciliation.

Test cases for wallet and UPI payments

Test cases
28 cases on payments that time out with no response, idempotency on retry, racing balances, caps across devices, collect request fraud, mandates and refunds.

Test cases for insurance claim submission

Test cases
28 cases on coverage at the date of loss, waiting periods, deductibles and sub limits, exclusions and riders, duplicate claims and settlement reconciliation.

Test cases for patient records in an EHR

Test cases
28 cases on duplicate detection and merge, wrong patient entry, units of measure, allergy and interaction alerting, break glass access and audit of reads.

Test cases for CRM lead management

Test cases
28 cases on duplicate leads under concurrency, routing and the unrouted fallback, round robin races, territory visibility, conversion and bulk import.

Test cases for an ERP purchase order

Test cases
28 cases on approval thresholds, amendments that must reset approval, budget commitment races, over receipt tolerance, three-way match and duplicate invoices.

Test cases for OTT video playback

Test cases
28 cases on bitrate recovery after a dip, DRM renewal mid stream, concurrent stream limits and leaked slots, resume conflicts, ad cue points and offline expiry.

Test cases for game level progression

Test cases
28 cases on save corruption during a crash write, cloud save conflicts, offline queue replay, unlock gating, currency exploits and purchase restore.

Test cases for a REST API

Test cases
28 cases on status code correctness, cross tenant resource access, mass assignment, idempotent retries, cursor pagination, rate limits and contract drift.

Test cases for SSO and social login

Test cases
28 cases on linking an account on an unverified email, state and code replay, redirect allow lists, token signature and issuer, deprovisioning and session rotation.

Test cases for subscription and billing

Test cases
28 cases on mid cycle proration, duplicate and out of order webhooks, renewal double charges, dunning and grace, trials, coupons, metered usage and tax.

Test cases for data tables, filters and sorting

Test cases
28 cases on unstable sorts across pages, filters that must reset pagination, selection surviving a filter change, bulk action scope and export fidelity.

Test cases for session timeout and concurrent login

Test cases
28 cases on tokens that survive sign out, refresh token reuse, idle against absolute lifetime, multi tab expiry, session limits and remote revocation.

Test cases for a multi step form wizard

Test cases
28 cases on values lost to back navigation, refresh and session expiry, step skipping, server side revalidation, duplicate submission and conditional branches.

Test cases for dashboards and analytics widgets

Test cases
28 cases on reconciling against source rows, widgets that disagree, timezone aggregation, zero baselines, no data shown as zero and permission leaks in aggregates.

Test cases for booking and reservation

Test cases
28 cases on concurrent bookings for the last slot, inventory holds that leak, payment without a booking, cancellation boundaries and channel sync.

Test cases for mobile app install and update

Test cases
28 cases on migration chains across skipped versions, crashes during post upgrade migration, forced update lockouts, deep links and clean reinstall.

Test cases for accessibility (WCAG 2.2 AA)

Test cases
28 cases on keyboard only completion, focus management, live region announcements, contrast, reflow at 320 pixels, target size and screen reader verification.

Test cases for performance and load

Test cases
28 cases on spikes with no ramp, recovery after peak, soak and leak detection, pool exhaustion, cold caches, retry storms and data correctness under load.

Test cases for the OWASP Top 10

Test cases
28 cases on broken access control, mass assignment, injection across every input surface, credential stuffing, session invalidation, SSRF and exposed secrets.

Test cases for cross browser compatibility

Test cases
28 cases on storage that throws in private mode, blocked third party cookies, engine date parsing, mobile viewport units, in app browsers and ad blockers.

Test cases for database and data integrity

Test cases
28 cases on uniqueness under concurrency, lost updates, counter races, orphaned rows, migration and backfill safety, replica lag and verified restores.

Test cases for localisation and multi language support

Test cases
28 cases on text expansion, concatenated sentences, plural rules, locale date parsing, decimal separators, right to left layout, collation and encoding.

Want your verification flow proven, not assumed?

QAble covers functional, boundary and security paths with ISTQB-certified engineers. Start with a free QA audit of your product.

Talk to QA Advisor