Start with a pending account

The useful question is what the new account may do before the address has been proved. A typed address is only a claim; it might contain a typo, belong to somebody else, or be controlled by an attacker. OWASP recommends verifying ownership before enabling account use. Keep the account in a pending state and prevent actions that depend on reliable delivery, such as retrieving private orders or using that address for recovery. If the shop permits a guest purchase, keep the guest order journey separate from registration and tell the buyer where their receipt will be sent. Show the address entered and offer a clear correction route before a message is sent. Do not tell the registrant that the mailbox is verified merely because an email provider accepted the outgoing message.

Bind the proof to the right account

Give each pending registration an internal account identifier and associate the verification challenge with that account and the exact address being verified. Generate a cryptographically random, hard-to-guess token; store only what is needed to check it, and give it a bounded lifetime. A successful redemption should atomically mark that challenge consumed and activate only its bound pending account. A second visit to the same link should display a safe already-used result, never repeat side effects. A token issued for an old address must not validate a corrected address. Avoid relying on a visible email parameter in the URL to decide which account is activated. OWASP's email guidance calls for single-use, time-limited verification tokens; these are properties of the server-side decision, not just wording in the email.

Make resend and correction predictable

A common failure is an innocent typo. Let a pending registrant correct the address through a controlled session or restart registration, then issue a new challenge for the new value and invalidate the old one. For resend, choose a simple rule such as replacing the prior unused challenge; explain that only the newest message works. Rate-limit requests by account and other appropriate signals so the feature cannot become a mail flood. If an address is already registered, avoid turning resend into a way to enumerate customers. A neutral response can direct the requester to sign in or recover access without confirming account existence. Do not silently create a second active account for the same identity merely because the first message was delayed.

Explain each state to the customer

The confirmation screen should state which address was entered, that the account remains pending, how to resend, and how to correct the address. Do not promise an exact arrival time that the business cannot control. The email should name the action, use a recognisable sender, and explain what to do if the recipient did not register; do not invite them to reply with a password. On success, show an explicit verified result and a next action. On expired or used links, say what happened without exposing private account details, and provide a fresh-request route. If the customer opens the link in another browser, the token can still prove inbox access, but privileged access should require the normal sign-in step rather than assuming the browser is the original registrant.

Walk through a wrong-address case

Imagine a shopper registers as mei@example.com but meant to enter mei.chan@example.com. The first address could be somebody else's inbox, so sending a link there must not grant access to the shopper's purchases. The page shows the pending address; the shopper corrects it while still in the registration session. The application invalidates the first challenge, binds a new challenge to the corrected address, and sends a replacement message. If the unintended recipient later clicks the old link, the server rejects it and reveals no order data. If the corrected recipient uses the new link twice, the first request changes the pending state and the second merely explains that the link was already redeemed. This scenario tests identity binding, state transitions and helpful recovery together.

Test the server decision, not just the email template

Test an unverified account against every protected route, including direct URLs and APIs, rather than trusting a disabled button. Exercise valid, expired, reused and malformed tokens; a token for a different account; an address corrected after the first send; concurrent redemptions; and multiple resend requests. Confirm that only one transition can win, old links fail, and protected data stays unavailable. Check the English and Traditional Chinese pages for the same state meanings and usable recovery links. Inspect analytics and logs for token leakage, and confirm the landing page's referrer behaviour. Finally, simulate mail delay and delivery failure: the customer should retain a truthful pending status and a route back, while staff should have a defined way to investigate without manually marking an unknown inbox as verified.

Keep the scope of proof honest

An email click proves control of that mailbox at the time of redemption. It does not prove a legal name, ownership of a business, or permanent control of the address. A merchant selling ordinary goods may decide this proof is sufficient for routine account activation, while a service with sensitive records needs additional controls for high-risk actions. Record the state and the time of verification separately from the date the account was created. If the address later changes, run the distinct email-change process rather than reusing the registration link. Make this distinction clear in product requirements so support staff do not treat a delivered message, an opened message, and a redeemed challenge as interchangeable evidence.

Separate delivery failure from verification failure

An email provider may accept a send request yet later bounce the message, defer delivery, or place it in a spam folder. None of those events verifies the mailbox. The product should distinguish “message requested”, “delivery failed” and “address verified” internally, while using customer language that does not overpromise what the provider knows. Give the registrant a way to retry after checking the displayed address, and a support path that does not ask them to forward a live token. Staff investigating a bounce should see enough masked information and timestamps to diagnose the case, but not the secret link. If delivery repeatedly fails, the pending account may need a documented expiry or cleanup rule; deleting it without warning can strand a shopper who has a separate guest order.

Avoid accidental account collisions

Email matching policy also matters at registration. OWASP advises lowercasing the domain, preserving the address as entered for display, and avoiding provider-specific tricks such as removing dots from a local part unless the system truly controls that behaviour. A shop should document how it compares local parts across sign-up, sign-in and recovery, then test visually similar and differently cased addresses against that one policy. Do not merge two pending registrations simply because a heuristic says the inboxes are probably equivalent. If the address conflicts with an existing account, guide the customer to the normal sign-in or recovery route without revealing protected account details. The verification link is evidence for one address and one pending identity, not permission to rewrite another customer's established account.

Give support a narrow investigation checklist

Support needs a decision tree for “I did not get the email” and “I did not sign up”. First confirm the user is on the genuine site and which masked address is pending. Then check send outcome, bounce status and resend limits, without reading or sending the token on the customer's behalf. For an unexpected message, tell the recipient that ignoring an unredeemed link leaves the account pending and give a way to report abuse; do not disclose who entered their address. Escalate repeated malicious registration attempts through abuse controls. Record the case outcome separately from account verification so a support note cannot accidentally grant access. This operational step turns the secure token design into a journey that a small team can actually manage.

Before release

  • Pending accounts cannot reach private routes
  • Only a current, bound, unused token activates the account
  • Correction and resend invalidate older links

Sources & further reading