SFMC does not update the email address in All Subscribers immediately in ALL scenarios - this is specific to the method you use for sending, see here:
https://mc.chat/subscriber-email-address-update-behavior/
In the first two scenarios where the send is initiated from Sales Cloud, the email address in the All Subscribers list will be updated at send time, but based on the current email address for the Lead or Contact in the Synchronized Data Extension, so you need to ensure that the synchronization interval is sufficient to allow for any email address changes on Lead or Contact records to be reflected in Marketing Cloud. By default, this is every 15 minutes.
For Data Extension based sends, the email address used to send an email to a Subscriber will not be updated based on the value of your email address field in your Data Extension. That’s because by default, this email address is only used when creating a new Subscriber record at send time.
If your Sendable Data Extension contains different email addresses for Subscribers who exist in the All Subscribers list, then you should consider sending the email from a Journey. Alternatively, you can update the email address of the affected Subscribers in the All Subscribers list before sending, or contact Salesforce support and request the default behaviour to be overridden, to allow the Email Address field in a Sendable Data Extension to update the Subscriber record at send time.
Note that if you are sending to a Salesforce Audience from Content Builder Send Flow, either a Salesforce Report, Campaign or a Salesforce Data Extension, then the email address will be updated at send time.
Also when an email address is updated from a Triggered Send, for example a Sales Cloud Triggered Send, an API-based Triggered Send, or a Journey Builder Send Email Activity (which uses a Triggered Send Definition behind the scenes) and the Subscriber status is ‘Held’, then it will be automatically reset to ‘Active’ when the email is sent. Note, this ‘status reset’ behaviour does not currently apply for triggered send definitions created using the Transactional Messaging API.
The way I set up an email change is this:
1 ) set up a field or similar in which the NEW email address is stored.
2 ) KEEP the OLD email address at the same time, until end of process
=
3 ) Build a service that
3a) validates the new email! List detective, suppression lists.... see closing notes. If the new email is invalid, break process and output an error. edit: consider also that you might not want to allow changing the new email to a value that is already used by another person, which could create duplicates through the backdoor.
3b) creates a dummy ID with a prefix such as
var prefix = emc_
var guid = Platform.Function.GUID()
var dummyID = guid + prefix
3c) sends out an email via the transactional API using dummyID + new email.
This will not update anything, but it creates a duplicate Contact.
We will get to that later.
The subscriber now receives an email to their new email, no existing contact is updated.
=
4 ) if this email is confirmed by clicking a link, make the link target a service that
4a) updates email on all subscribers from OLD to NEW value.
4b) changes the OLD email field to value of NEW email in your starting location.
4c) empties NEW email field in starting location
4d) makes sure that everything relevant for your business logic, that was stored using the old email as key (think auto suppression lists - sendable DEs with PK email address), is updated like all subscribers.
4e) updates the email in the master system, could be SFSC, could be SFMC, could be something completely different; depends on your setup
=
5 ) set up daily contact deletion automation; Determine a time after which you say the link does no longer need to work (1 day, 14 days...)
Select all people from All Subscribers whose Key starts with your prefix and whose creation date is older than your defined time.
Something like
SELECT SubscriberKey
FROM _subscribers
WHERE key LIKE 'emc_%'
AND DateJoined <= /* insert your timing */
Insert them into your contact deletion process, which clears the duplicate and will make the confirmation link non-functional. Note that this should happen regardless of user confirming or not. All your dummy IDs have to go.
optional 6) If you need tracking information about that email you sent for confirmation, make sure you back that tracking data up somewhere before the contact with all its associated data is deleted / anonymized.
==
limitations: Anything that prevents transactional sendouts makes this fail.
List detective blocks the transactional message, if the new email is invalid for list detective, the whole process cannot be completed.
Auto suppressions for transactional messages: if the new email is on one, the whole process fails.
This can get especially fun if a new email address is 100% VALID for other systems in your infrastructure, but INVALID for marketing cloud (because list detective says that you cannot be [email protected] !).
The other system might require the change, but SFMC cannot perform it.
So the whole process only makes sense for subscribers intended for use in marketing cloud.
For everything else (think of a connected infrastructure - "i want to change email to a commerce cloud profile"), the implementation pattern is still useable, but SFMC is the wrong system to implement the email change in. You cannot stop SFMC from using its validation logic (you can only soften it up).
So SFMC by design enforces blocking logics that make no sense in any other system, preventing a commerce cloud profile's email change to [email protected] (which is a valid thing to do) because Marketing Cloud has a list detective that decides this. This is absurd and you have to avoid coming into a situation where you have to explain this.