Matching inbound emails without a watermark

Consider the following scenario: An email hits ServiceNow to open a new Incident. This creates a new Incident record within their instance as expected. That is until someone else responds with a “reply-all” message to that initial email that opened the Incident ticket. Because this second “reply-all” has never touched the ServiceNow instance, it lacks a watermark and thus ServiceNow will treat it as a new message and open a second Incident. This has obvious pitfalls for clients but luckily there is a solution.

On the header of every email is something called a “Message-ID” – this is standard. The Message-ID is essentially a unique identifier for an email, which is great for us. In order to accurately determine what is a reply to an Incident creating email without the assistance of ServiceNow’s automatic watermarking, we’ll need to store this Message-ID on the actual Incident form in the initial Incident creation.
Please note that my intent with this rule was simply to append the reply as a comment in the activity log. You can obviously choose to incorporate other elements of the reply email if you so wish to do so.

Follow the below steps to accomplish this solution:

1) Create a 100 character string field called “Reply Code” on the Incident table. Up to you on this but I prefer to keep this field hidden and off the form layout.

2) Navigate to the inbound action that creates Incidents. You will need to store the Message ID from this email on the form somewhere. I used the following code to correctly parse out the Message-ID and store it:

var message_id = email.headers;
var findID = message_id.search(‘\nMessage-ID:’);
var initSub = message_id.substring(findID);
var endS = initSub.search(‘>’);
var subID = initSub.substring(13, endS);

current.u_reply_code = subID;

3) Next you will need to ensure that replies are properly indexing and searching for this Incident based on the stored reply code. Create a new inbound action called “Reply Incident” that processes before your Incident creation – change the order to do this (if order is 100 on the rule that creates Incidents, make the reply rule 95). I used the following code to match on the reply-code:

var message_id = email.headers;
var findIDref = message_id.search(‘References:’);
var initSubref = message_id.substring(findIDref);
var endSref = initSubref.search(‘>’);
var subIDref = initSubref.substring(12, endSref);

var incidentLookup = new GlideRecord(‘incident’);
incidentLookup.addQuery(‘u_reply_code’, subIDref);
incidentLookup.query();

if (incidentLookup.next()) {
var trimBody = email.body_text;
var loc = trimBody.search(‘From: ‘);
trimBody = trimBody.substring(0, loc);
incidentLookup.comments = “Received from: ” + email.origemail + “\n\n” + trimBody;
incidentLookup.update();
event.state=”stop_processing”;
}

Note that I am using the header “References” to find the matching Message-ID. It works as follows: Replies to your initial message that opened the Incident will contain the header “References”. No matter how nested the replies are, the original message id will always be contained in the “References” id in message headers.

This should complete the process. Test your rule out and ensure your reply code is getting stored correctly.