Thread Id versus Email Header

As you are aware, Salesforce is introducing a new threading behavior with the Winter ’21 release. As of today, the feature will be enforced in the Summer ’23 release. Please check the official Salesforce web site (Opt in or opt out on the New Threading Behavior for Email-to-Case) for the latest status, as the enforcement date has been moved multiple times.

Update 9/16/2022: As of September 15th, 2002, Salesforce has removed the Summer ’23 enforcement date.

Let’s take a very quick look at the differences in behavior. Then let’s explore how Email-to-Flow can make your transition easier.

Original Threading Behavior (Thread Id)

The original threading logic was based on a generated thread Id. Outbound Salesforce emails included a generated thread id. These thread ids where added to the email subject and/or included within the email text body. Email-to-Case decoded the inbound email’s thread id to confirm the correct salesforce instance and to identify the correct case id (see On-Demand ‘Email-to-Case’ logic for thread IDs included in inbound email for more details).

While simple enough, this threading behavior could prove problematic in a number of situations. A client could accidentally remove or modify the thread id during a correspondence, resulting in email-to-case creating a new case rather than linking to the original case.

Note: For custom email service implementations, a case Id could be decoded from a thread id leveraging the getCaseIdFromEmailThreadId method (getCaseIdFromEmailThreadId(emailThreadId)). This method has also been deprecated. Warning: It will produce permission errors once you opt into the new threading behavior. For custom outbound emails leveraging templates, the thread id could be include via a merge field, {!Case.Thread_id}. This functionality has been deprecated. Warning: The merge field will NOT error. However, it will generate a null value once you opt into the new threading behavior.

New Threading Behavior (Email Header Message Id)

The new threading behavior leverages the email header (specifically the Message-Id, In-Reply-To and References header values). Outbound Salesforce emails include a unique Message-ID value. This value is stored in the email message record that is created. Emai-to-Case leverages the In-Reply-To and References header values to find the matching Message-ID value (and therefore the matching original case).

Note: For custom email service implementations, a case id can be decoded from the email headers leveraging the getCaseIdFromEmailHeaders method (getCaseIdFromEmailHeaders(headers)).

Great, but how do I transition from the old behavior to the new behavior?

The technical “transition” is pretty basic. If you are running standard Email-to-Case, simply go to Setup -> Release Updates -> Opt In to Disable Ref ID and Transition to New Email Threading Behavior. (TEST, TEST and then TEST again!).

If you have any customization related to the Email-to-Case process, it is highly recommended that you plan your transition. The transition may require modifications to existing processes, the implementation of new process, additional data loads, etc. Plan accordingly! Don’t leave the transition and planning until the last minute.

If you have a custom implementation, there might some details to consider.

Custom Code Considerations

If you have a custom email service, you will need to migrate your existing logic from the getCaseIdFromEmailThreadId() method to the getCaseIdFromEmailHeaders() method. Again, once you opt into the new threading behavior, getCaseIdFromEmailThreadId() will produce an error (regardless of you API version).

If you are generating custom emails (and a custom thread id), you will need to consider enhancing the existing logic and/or introducing addition logic. If you require replies to emails to attach to the original case, you may need being creating custom email message records (or maybe custom linking logic). You might want to refer to a discussion on custom email linking back to cases here Email-To-Flow, Custom Email that Links back to a Case.

Great! That’s it?

Well, it really depends on your business. Specifically, it really depends on the longevity of your case cycles.

Other Considerations

The new threading behavior relies on the existence of an email message record with the Message Identifier field populated. You will need to ensure that your open cases (i.e. cases that you expect future email communication) have email message records and that those records have the message identified field populated. Good News! Salesforce has been automatically populating the Message Identifier field for a while. But it’s always a good idea to validate your data.

To get a sense of your message identifier data, open up Workbench and execute the following query. This will give you quick snapshot of your open cases with email message records missing the message identifier.

select count(id), incoming, max(createdDate)
from emailMessage
where messageIdentifier = null

and isClosed = false
group by incoming

If the message identifier field is not populated for all your cases or your previous custom email process did not include the creation of email messages, you will need to make a decision.

When a link can not be established, a new case record will be created instead. In this is acceptable, you need not do anything. If this is problematic, you have a couple of options. Unfortunately, there is no easy way to recreate email message after the fact, as the message identifier is no longer available. But, you can attempt to populate the message identifier on existing email message records from the stored email headers.

Or, maybe you want to implement a redundant threading process instead.

Redundant Threading Process

A redundant threading process can vary by business. However, at its base, it is a process which would evaluate inbound emails using both the original thread id logic (obviously custom once you opt in) and the new email header message id logic.

A solution like Email-to-Flow (Introducing Email-To-Flow, a low-code Email Service) can provide the flexibility to implement a transitional redundant threading process. For example, a redundant threading process would attempt to find a matching message identifier first. If none, found, and a Thread Id is found in the email, then an attempt would be made by the original threading logic.

Have a unique requirement? Give us a ping.