function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Collin EdlCollin Edl 

Email to Case CC'd on Emails and Creating Duplicate Cases

We have a standard support email that creates a case in Salesforce. Oftentimes a client will email someone, CC our support account and then those two people will email each other back and forth, every time having the support email CC'd, thus creating duplicate cases for the same issue. Looking for a way to have it where if the email has the same subject line, then all those interactions will be on the same case and no new case created.

Found some code online, tweaked it a little but it doesn't seem to be working in the sandbox. Any advise on where it could be failing?

CaseEmailInBoundUtilities
public with sharing class CaseEmailInBoundUtilities {

private Static Boolean TRACE = true;

protected Case theCase = null;
protected Messaging.InboundEmail inboundEmail;
protected String defaultCaseOwnerId;

public CaseEmailInBoundUtilities() {
 Group[] queues = [select Id, Name from Group where Name = 'Client Relations Queue'];
 this.defaultCaseOwnerId = queues[0].Id;  
}

public Messaging.InboundEmailResult processInboundEmail(Messaging.InboundEmail email)
{
 Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
 result.success = true;
 this.inboundEmail = email;
 

 String caseNumber = extractRef(email.subject);
 if(caseNumber != null)
 {  
  if(TRACE)system.debug(Logginglevel.ERROR,'CaseEmailInBoundUtilities.  extracted case number: "' + caseNumber + '"');
  this.theCase = locateByCaseNumberAsString(caseNumber);
  if(this.theCase == null) {
   // TODO email error message to SysAdmin
   system.debug(Logginglevel.ERROR,'CaseEmailInBoundUtilities.  Create a new case.  Could not find case number: "' + caseNumber + '"');
  }
 } else {
  // try to match subject
  String mainSubject = extractMainSubject(email.subject);
  Case[] matchingCases = [Select Id, CaseNumber, Subject, Description from Case where Subject = :mainSubject
   and CreatedDate = LAST_N_DAYS:5];
  if(matchingCases.size() == 1) {
   this.theCase = matchingCases[0];
  } else 
  {
   system.debug(Logginglevel.ERROR,'CaseEmailInBoundUtilities.  Create a new case because we found '+matchingCases.size() + ' cases with the subject: "' + mainSubject + '"');
  }
 }
 if(this.theCase == null) {
  // else create a new Case
  this.theCase = new Case();
  theCase.SuppliedEmail = email.fromAddress;
  theCase.SuppliedName = email.fromName;
  theCase.Status = 'New';
  theCase.Priority = 'Low';
  theCase.OwnerId = this.defaultCaseOwnerId;
        theCase.Origin = 'Inbound Email';
  theCase.Subject = email.Subject;
  theCase.Description = email.plainTextBody;
  
  Contact[] contacts = [SELECT Id, Name, AccountId, Email FROM Contact WHERE Email = :email.fromAddress];
  if(contacts.size() >0) 
  {
   Contact theContact = contacts[0];
   theCase.ContactId = theContact.Id;
   theCase.AccountId = theContact.AccountId;   
   if(contacts.size() > 1) {
    // Could-Should create a new Case here to get CS to resolve this....
    theCase.Description = 'Note: there is more than on Contact with this email address. Fix this. ' + theCase.Description;
   }
  }
  insertSObject(this.theCase);
 }

 createEmailMessage(theCase,email);
 handleAttachments(theCase, email);

  // send success notification. This can be disabled once we know the code is stable.
 // if(result.success)
 // {
 //  String successMessage = 'Successful processing of inbound email  \n'+ noteBody;
 //  TriggerErrorNotification.reportInfo(messagePrefix+ ' success ',successMessage);      
 // }
 return result;
}

// Save attachments, if any
private void handleAttachments(Case theCase, Messaging.InboundEmail email) {
 if(email.textAttachments!=null && email.textAttachments.size() >0) {
  for (Messaging.Inboundemail.TextAttachment tAttachment : email.textAttachments) {
    Attachment attachment = new Attachment();  
    attachment.Name = tAttachment.fileName;
    attachment.Body = Blob.valueOf(tAttachment.body);
    attachment.ParentId = theCase.Id;
    insertSObject(attachment);
  }
 }
 
 if(email.binaryAttachments!=null && email.binaryAttachments.size() >0) {
  for (Messaging.Inboundemail.BinaryAttachment bAttachment : email.binaryAttachments) {
    Attachment attachment = new Attachment();
    attachment.Name = bAttachment.fileName;
    attachment.Body = bAttachment.body;
    attachment.ParentId = theCase.Id;
    insertSObject(attachment);
  }
 } 
}

private void insertSObject(sObject obj) {
 try {insert obj;} catch (System.DmlException e) {handleError(e, 'Could not insert obj '+ obj);}
}

private String limitLength(String input, Integer maxLength)
{
 String results;
 if(input != null && input.length() > maxLength)
  results = input.substring(0,maxLength);
 else 
  results = input;
 return results;
}

private void createEmailMessage(Case theCase, Messaging.InboundEmail email) {
 String value;
 Integer maxlength;
 EmailMessage theEmail = new EmailMessage();
 theEmail.ParentId = theCase.Id;
 theEmail.Incoming = true;
 theEmail.Status = '1'; //set to new
 Schema.DescribeFieldResult F = EmailMessage.HtmlBody.getDescribe();
 //.HtmlBody.getDescribe();
 maxlength = F.getLength();
 theEmail.Subject = limitLength(email.Subject, EmailMessage.Subject.getDescribe().getLength());
 theEmail.MessageDate = datetime.now();
 theEmail.HtmlBody = limitLength(email.htmlBody,EmailMessage.HtmlBody.getDescribe().getLength());  
 theEmail.TextBody = limitLength(email.plainTextBody,EmailMessage.TextBody.getDescribe().getLength());

 /* **** To */
 value = '';
 if(email.toAddresses != null) {
  Boolean seenOne= false;
  for(String to : email.toAddresses) {
   if(seenOne) {
    value += ';\n';
   }
   to  = extractAddress(to);
   system.debug('ToAddress: ' + to);
   value += to;
   seenOne = true;
  }
 }
 theEmail.ToAddress = limitLength(value,EmailMessage.ToAddress.getDescribe().getLength());
 
 /* **** From */
 theEmail.FromName = email.fromName;
 theEmail.FromAddress = email.fromAddress;
 
 /* **** CC */
 value = '';
 if(email.ccAddresses != null) {
  Boolean seenOne= false;
  for(String cc : email.ccAddresses) {
   if(seenOne) {
    value += ';\n';
   }
   cc  = extractAddress(cc);
   system.debug('CcAddress: ' + cc);
   value += cc;
   seenOne = true;
  }
 }
 theEmail.CcAddress = limitLength(value,EmailMessage.CcAddress.getDescribe().getLength()); 
 insertSObject(theEmail);
}



private void handleError(System.DmlException e,  String message){
 String baseURL = URL.getSalesforceBaseUrl().toExternalForm() + '/';
 if(TRACE)system.debug(baseURL);
 String caseURL;  
 String msg = message + '\n';
 if(this.theCase != null)
 {
  caseURL = baseURL + theCase.Id;
  msg += '\n';
  msg += 'Originating Case Number: ' + theCase.CaseNumber + '  '+ caseURL+'\n';   
 }
 if(this.inboundEmail != null) {
  msg += '\nEmail:';
  msg += '  subject: ' + inboundEmail.Subject + '\n'; 
  msg += '  from: ' + inboundEmail.FromName + '\n'; 
  msg += '  address: ' + inboundEmail.FromAddress + '\n'; 
 }
 if(e != null) { // compose the DmlException message on one line to minimize the number of untested lines.  AFAIK easy to instantiate a DmlException in a unit test. 
  msg += '\n';
  msg += 'EXCEPTION:\n  Error: ' + e.getMessage() + '\n  Type: ' + e.getTypeName() + '\n  Line Number: ' + e.getLineNumber() + '\n  Trace:\n' + e.getStackTraceString() + '\n(end stack trace)\n';
 }

 Case errCase = new Case();
 errCase.OwnerId = this.defaultCaseOwnerId;
 errCase.Status = 'New';
 errCase.Priority = 'Low';
    errCase.Origin = 'Email';
 errCase.Subject = 'Error processing incoming email';
 errCase.Description = limitLength(msg,Case.Description.getDescribe().getLength());
 insert errCase;
 errCase = [Select Id, CaseNumber from Case where Id = :errCase.Id limit 1];  

 caseURL = baseURL + errCase.Id;
 msg += '\n\n';
 msg += 'Created new Case number ' + errCase.CaseNumber + ' for this error.  See: ' + caseURL +'\n'; 

//TriggerErrorNotification.reportError('CaseEmailInBoundUtilities', msg); 

}


/*
Given a case number such as 8144 find the exact case that use this number. Note that CaseNumber is a string field 
that may have any number of leading zeros. 
*/
private Case locateByCaseNumberAsString(String caseNumberStr){
 Integer target = Integer.valueOf(caseNumberStr);
 Case theResult = null;
 String caseNumber = '%' + String.valueOf(target);
 Case[] matchingCases = [Select Id, CaseNumber, Subject, Description from Case where CaseNumber like :caseNumber];
 for(Case aCase: matchingCases) {
  Integer cnum = Integer.valueOf(aCase.CaseNumber);
  if(cnum == target) {
  theResult = aCase;
  break;
  }
 }
 return theResult;
}

/*
Look for the case reference in the email subject line.  First search for a case reference using the
standard Salesforce method of creating that complicated and non-user-friendly reference.  Do this first
so it takes precedence.

But, also search for the case number itself. This is user-friendly!
*/

private String extractRef(String emailSubject)
{
 String itemRef = null;
// add test for null
 if(emailSubject == null)
  return null;
 String target = emailSubject.toLowerCase();
 String patternString;
 Pattern thePattern;
 Matcher matcher;
 
/*  Take the text between the period and ":ref"  For example in the ref [ ref:00D7JFzw.5007H3Rh8:ref ] extract 5007H3Rh8
 Take that text and remove the 5007. For example H3Rh8 
 Append H3Rh8 to https://na5.salesforce.com/5007000000  to produce https://na5.salesforce.com/5007000000H3Rh8.   This is your link to get to the case.
*/  
 patternString = '.*ref:(.{8}).(.{4})(.+):ref.*';
 thePattern = Pattern.compile(patternString);
 matcher = thePattern.matcher(emailSubject); // do not change to lower case for this test because Id's are case sensitive
  
 if (matcher.matches()) {
  String caseId = matcher.group(2) + '000000' + matcher.group(3);
  if(TRACE) system.debug(Logginglevel.ERROR,'extractRef "' + caseId + '"');    
  Case[] matchingCases = [Select CaseNumber from Case where Id = :caseId];
  if(matchingCases.size() == 1) {
   Case theCase = matchingCases[0];
   itemRef = theCase.CaseNumber;
  }    
 }  
 if(itemRef == null) {
  // extract the Case Number from the email Subject
  // Re: Test two numbers Case: 30088 and Case: 30089'
  // returns 30089, the last pattern matched
// Change the pattern to allow for more variations:
  patternString = '.*case\\s*[;:=#]?\\s*([0-9]+).*';
  thePattern = Pattern.compile(patternString);
  matcher = thePattern.matcher(target);
  
  if (matcher.matches()) {
   itemRef = matcher.group(1);
   if(TRACE) system.debug('Extracted case number ' + itemRef); 
  }
 }

 return itemRef; 
}

private String extractMainSubject(String emailSubject)
{
 if(emailSubject == null || emailSubject.length() < 3)
  return emailSubject;
 String[] prefixes = new String[] {'fw:','re:', 'automatic reply:', 'out of office autoreply:', 'out of office'};  
 String target = emailSubject.toLowerCase();
 for(String prefix: prefixes) {
  Integer index = target.indexOf(prefix); 
  if(index == 0 ){
   String mainSubject = emailSubject.substring(prefix.length(),emailSubject.length());
   return mainSubject.trim();
  }  
 }
 return emailSubject; 
}

private String extractAddress(String inAddress)
{
 String address;
 String patternString;
 Pattern thePattern;
 Matcher matcher;
 patternString = '.*<(.*)>.*';
 thePattern = Pattern.compile(patternString);
 matcher = thePattern.matcher(inAddress);
 if (matcher.matches()) {
  address = matcher.group(1);
  system.debug('Extracted address ' + address); 
 }
 else
 {
  address = inAddress;
  system.debug('Did not match angle-address ' + address);   
 }
 return address;
}
}

CaseEmailInBoundHandler
global class CaseEmailInBoundHandler implements Messaging.InboundEmailHandler {

    global Messaging.InboundEmailResult handleInboundEmail(
       Messaging.InboundEmail email,
       Messaging.InboundEnvelope envelope) {

 CaseEmailInBoundUtilities handler = new CaseEmailInBoundUtilities();
        Messaging.InboundEmailResult result = handler.processInboundEmail(email);
        return result;        
    }
}


 
GhanshyamChoudhariGhanshyamChoudhari
  1. while creating email subject add case number in the email subject.
  2. check email subject contains case number if found then add all those interactions will be in the same case.
sai koushik p 14sai koushik p 14
Hi Collin Edl i am also having same recruitment so can u help me.if you have solved for this recruitment.