Keep a clear state machine

Define requested, pending, confirmed, rejected, expired, and rolled-back states. State which address receives login and recovery mail in each state. A second email-change request should cancel or replace the first under a written rule. Test old links after replacement. Treat a new email as untrusted until it proves control; do not send private account data to it just because it was typed into a form.

Test cases and proof

Use test accounts and test data
CaseExpected resultProof to keep
New email entered with stale sessionRequire fresh proofChange response
New inbox confirms but old inbox objectsApply hold or reversal policyAccount state
Link is reused after completionReject reuseToken record

Synthetic example

The old email receives a change notice while the new email receives a confirmation link. Decide which event makes the address active. Test expired links, a second pending change, and an objection from the old inbox.

Evidence to keep

Keep a timeline of the request, old-address notice, new-address confirmation, objection, and final activation. Use fake inboxes that the team controls. The evidence should show which address receives a password reset at each point. A stale link from an earlier request must not activate a new change after the customer starts over.

Run two pending email changes in quick order. Confirm the first link after the second request starts. The older link should not take control of the account. Then confirm the current link and check that all future recovery messages go to the active address under the product rule.

A pending email has limited power

A new address typed into a form has not proved control. Until the chosen confirmation step ends, it should receive only its narrow verification message, not statements, recovery links, or private alerts. A new change request must also invalidate or supersede old pending links under one clear rule. An objection from the old inbox may call for a hold and human review. Test these paths with two test inboxes and a second signed-in device. A normal confirmation screen can look right while the recovery mail already moved; check actual deliveries.

Related reading

Why these checks matter

OWASP’s authentication guide treats account recovery as a sensitive flow. NIST’s guidance separates authenticator recovery and account notice. A new email can become a future recovery route, so this test checks the pending state and old-address notice before it becomes active.

Give pending mail one narrow purpose

A pending address must receive its verification message, or it cannot prove inbox control. Until the chosen checks finish, it must not receive password reset, statements, or other private account content. Bind the verification token to account, exact pending address, request version, purpose, and expiry. A token for first@example.test cannot activate second@example.test.

Synthetic change E1 requests first@example.test. E2 replaces it with second@example.test before confirmation. Mark E1 superseded. Replay E1 and expect no change to login or recovery delivery. Confirm E2 with fresh proof under the policy, then try its token again. Check actual message destinations as well as the database email value.

Treat reversal as a sensitive change too

A notice sent to the old inbox may offer a report-abuse route. Possession of that inbox alone should not silently revert a completed change and seize the account under a weak reversal flow. Bind any objection token to its request and define whether it freezes sensitive changes or opens a reviewed case. Expire it and test reuse.

Run MFA-enabled and non-MFA fixtures under their chosen rules. The OWASP email-change guidance gives separate processes for those cases. NIST recovery guidance is broader context, not the exact email-change contract. Save request version, proof event, token purpose, active address after each transition, reset-mail destination, and notice result. An expired E2 must leave the old active address intact until a valid change finishes.

Source