+ Start a Discussion
Michael Hedrick 2Michael Hedrick 2 

Email service Email Address

Hello All,
I have created an email service that allows the user to send an email from the Lead object in Salesforce and have the replied email be attched to the Lead record as a Task. 
The issue is that if the Customer does not select "Reply All" the replied to email will not get associated back to the Lead record because the email service email address is being added to the email and is not hte default from email address. 
So is there a way to make Email Service Email Address selectable?  Or can the Email Service Email Address be an organizational wide email address? 
Thanks,
M
  
Best Answer chosen by Michael Hedrick 2
Om PrakashOm Prakash
Please add your  Email Service Email Address in organizational wide email addres.
You need to debug myPlainText in code after line number 13 then you can verify that email service after copy verification link from debug log.
During sending you will send from number as Email service Address then reply will auto route and above code will work.

All Answers

Om PrakashOm Prakash
You can achieve this by adding Lead id in end of the email content while sending email.
(We don't want to show the record ID to email receipent so we can add font color as white)
String htmlEmailBody = 'Your original email content';
htmlEmailBody += '<br><font color="white"> RecordId:-' + objLeadId + '</font>';
When they reply you can parse the lead id in email service class and query related lead. Then its easy for you to related task with original record.
global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope env) {
	String emailBody = email.plainTextBody != null ? email.plainTextBody : email.HTMLBody ;   //Get email body
	String  relatedRecordId = emailBody.subStringAfter('RecordId:-');
	if(String.isNotBlank(relatedRecordId)){
		relatedRecordId = relatedRecordId.trim();
		// SOQL here with record id on related object
	}
}


 
Michael Hedrick 2Michael Hedrick 2
Om,
Thank you for the reply.  Does this syntax need to be added to an HTML email template?
String htmlEmailBody = 'Your original email content';
htmlEmailBody += '<br><font color="white"> RecordId:-' + objLeadId + '</font>';

Also, here is my code :
global class EmailLeadReplyCreateTask implements Messaging.InboundEmailHandler {
 
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email, 
                                                       Messaging.InboundEnvelope env){
 
    // Create an InboundEmailResult object for returning the result of the 
    // Apex Email Service
    Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();
  
    String myPlainText= '';
    
    // Add the email plain text into the local variable 
    myPlainText = email.plainTextBody;
   
    // New Task object to be created
    Task[] newTask = new Task[0];
   
    // Try to look up any Leads based on the email from address
    // If there is more than one Lead with the same email address,
    // an exception will be thrown and the catch statement will be called.
    try {
      Lead vLead = [SELECT Id, Name, Email
        FROM Lead
        WHERE Email = :email.fromAddress
        LIMIT 1];
      
      // Add a new Task to the lead record we just found above.
      newTask.add(new Task(Description =  myPlainText,
           Priority = 'Normal',
           Status = 'Inbound Email',
           Subject = email.subject,
           WhoId = vLead.Id));
     
     // Insert the new Task 
     insert newTask;    
     
     System.debug('New Task Object: ' + newTask );   
    }
    // If an exception occurs when the query accesses 
    // the Lead record, a QueryException is called.
    // The exception is written to the Apex debug log.
   catch (QueryException e) {
       System.debug('Query Issue: ' + e);
   }
   
   // Set the result to true. No need to send an email back to the user 
   // with an error message
   result.success = true;
   
   // Return the result for the Apex Email Service
   return result;
  }
}
I tried modifying th Class to include the variable Id but I keep getting an error.
Lead vLead = [SELECT Id, Name, Email
        FROM Lead
        WHERE Id= :email.relatedRecordId 
        LIMIT 1];


 
Michael Hedrick 2Michael Hedrick 2
Om,
Currently the Salesforce users are just clicking the 'Send an Email' button the Lead record so the email body is free form.
Thanks,
M
Om PrakashOm Prakash
Hi Michael,
If you are using HTML Email template then its little easy. Add below line as last line of email template
<font color="white"> RecordId:-{!Lead.Id}</font>
Now your code will be modified as bellow
global class EmailLeadReplyCreateTask implements Messaging.InboundEmailHandler {
 
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email, 
                                                       Messaging.InboundEnvelope env){
 
    // Create an InboundEmailResult object for returning the result of the 
    // Apex Email Service
    Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();
  
    String myPlainText= '';
    
    // Add the email plain text into the local variable 
    myPlainText = email.plainTextBody;
   
    // New Task object to be created
    Task[] newTask = new Task[0];
   
    // Try to look up any Leads based on the record id 
    try {
    String  relatedRecordId = myPlainText.subStringAfter('RecordId:-');
	Lead vLead = new Lead(); // Optionally initialized to prevent null pointer in line 45
	if(String.isNotBlank(relatedRecordId)){
		relatedRecordId = relatedRecordId.trim();
		List<Lead> lstLead = [SELECT Id, Name, Email
        FROM Lead
        WHERE Id = : relatedRecordId 
        LIMIT 1];
		if(lstLead.size() > 0){
			vLead = lstLead[0];
		}
	}
	
     /* Lead vLead = [SELECT Id, Name, Email
        FROM Lead
        WHERE Email = :email.fromAddress
        LIMIT 1];*/
      
      // Add a new Task to the lead record we just found above.
      newTask.add(new Task(Description =  myPlainText,
           Priority = 'Normal',
           Status = 'Inbound Email',
           Subject = email.subject,
           WhoId = vLead.Id));
     
     // Insert the new Task 
     insert newTask;    
     
     System.debug('New Task Object: ' + newTask );   
    }
    // If an exception occurs when the query accesses 
    // the Lead record, a QueryException is called.
    // The exception is written to the Apex debug log.
   catch (QueryException e) {
       System.debug('Query Issue: ' + e);
   }
   
   // Set the result to true. No need to send an email back to the user 
   // with an error message
   result.success = true;
   
   // Return the result for the Apex Email Service
   return result;
  }
}

Let me know if still any issues

 
Tarun Nagpal 12Tarun Nagpal 12
Thanks alot Om Prakash,
This above approach is the best we can use it to hide anything in the HTML Email Template..
Really Impressive.
 
Michael Hedrick 2Michael Hedrick 2
Om Prakash,
Thank you for the reply.  The replied email is not going back to the initial Lead record.  Could it be an issue that the Lead Id field is in the HTML body and not a plain text body?

Cheers,
M
Om PrakashOm Prakash
Hi Michael,
Please debug relatedRecordId. I think any extra character is coming after record id in variable relatedRecordId.
If yes then take first 15 character (After trim)  from variable relatedRecordId in code then it will fetch initial Lead record.
relatedRecordId = relatedRecordId.trim();
relatedRecordId = relatedRecordId.substring(0,15);
In Email template we have option to "Copy text from HTML version" in Text-Only Email Content, so html body or plain text body will not cause issue.
 
Michael Hedrick 2Michael Hedrick 2
Hey Om Prakash,
I am not seeing a log in the Developer Console when I reply to the email.  I do not think its triggering the email service.  So I put my original code back in and debugged for the Lead ID in the body of the Email and I could see the Id so that work and it created the activty but I have to include the Email Service email and had to reply all to the email.
Do I need to do something with the Email Service?

Thanks,
M
Om PrakashOm Prakash
Strange. I just tried similar code in my Developer Edition org and it’s working as expected. Try adding ‘record id fetch’ logic in your original code. It should work.
Michael Hedrick 2Michael Hedrick 2
I will give this a try again.  And I do need the Email service configured and an email address record with it correct?
Thanks,
M,
 
Om PrakashOm Prakash
Yes, User will reply on the configured email service email id only. Since we are making query by using record Id so matching email on lead record is not required.
Michael Hedrick 2Michael Hedrick 2
Om Prakash.
Still not working.  I do not see any activity in the logs where the Email service is even triggering on teh reply.
Is it my Email Service Configuration?  I left the 'Accept Email from'  blank which I thought would accept all email.  Is this not corrrect?
global class EmailLeadReplyCreateTask implements Messaging.InboundEmailHandler {
 
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email, 
                                                       Messaging.InboundEnvelope env){
 
    // Create an InboundEmailResult object for returning the result of the 
    // Apex Email Service
    Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();
  
    String myPlainText= '';
    
    // Add the email plain text into the local variable 
    myPlainText = email.plainTextBody;
   
    // New Task object to be created
    Task[] newTask = new Task[0];
   
    // Try to look up any Leads based on the email from address
    // If there is more than one Lead with the same email address,
    // an exception will be thrown and the catch statement will be called.
    try {
    
        String  relatedRecordId = myPlainText.subStringAfter('RecordId:-');
        System.debug('Lead Id:' + relatedRecordId); 
          
        relatedRecordId = relatedRecordId.trim();
        relatedRecordId = relatedRecordId.substring(0,15);
    
      Lead vLead = [SELECT Id, Name, Email
        FROM Lead
        WHERE Id = : relatedRecordId
        LIMIT 1];
      
      // Add a new Task to the lead record we just found above.
      newTask.add(new Task(Description =  myPlainText,
           Priority = 'Normal',
           Status = 'Inbound Email',
           Subject = email.subject,
           WhoId = vLead.Id));
     
     // Insert the new Task 
     insert newTask;    
     
     System.debug('New Task Object: ' + newTask );   
    }
    // If an exception occurs when the query accesses 
    // the Lead record, a QueryException is called.
    // The exception is written to the Apex debug log.
   catch (QueryException e) {
       System.debug('Query Issue: ' + e);
   }
   
   // Set the result to true. No need to send an email back to the user 
   // with an error message
   result.success = true;
   
   // Return the result for the Apex Email Service
   return result;
  }
}

 
Om PrakashOm Prakash
Hi,
Can you please check if user is replying on the email service email address?
Also "Email Service" and "Email Service Address" both are active?
If yes then debug log must be created for Email Service apex class

 
Michael Hedrick 2Michael Hedrick 2
Hey Om Prakash,
How can the user reply to the email service email address?
Here is what the user sees when they are sending an email.
User-added image 

Now if I add it to the email service email address to CC and the user replies all then yes the Email Service Apex Class is triggered.
Om PrakashOm Prakash
Please add your  Email Service Email Address in organizational wide email addres.
You need to debug myPlainText in code after line number 13 then you can verify that email service after copy verification link from debug log.
During sending you will send from number as Email service Address then reply will auto route and above code will work.
This was selected as the best answer
Michael Hedrick 2Michael Hedrick 2
Ok.  But I cannot verify the Email Service Email Address correct?  
 
Michael Hedrick 2Michael Hedrick 2
I recieved an error saying:
"Undeliverable: Sandbox: Verify your Salesforce Organization-Wide Address"
Michael Hedrick 2Michael Hedrick 2
Ok. Edited Apex Class and added debug line. Added Email Service Email Address to Ord Wide email addresses and saved.
Recieved error in my inbox
The apex class EmailLeadReplyCreateTask failed due to: System.StringException: Ending position out of bounds: 15

---------------

The attached email could not be processed because the Apex class EmailLeadReplyCreateTask failed.

System.StringException: Ending position out of bounds: 15

Class.EmailLeadReplyCreateTask.handleInboundEmail: line 28, column 1

Here is the Class:
global class EmailLeadReplyCreateTask implements Messaging.InboundEmailHandler {
 
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email, 
                                                       Messaging.InboundEnvelope env){
 
    // Create an InboundEmailResult object for returning the result of the 
    // Apex Email Service
    Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();
  
    String myPlainText= '';
    
    // Add the email plain text into the local variable 
    myPlainText = email.plainTextBody;
    System.debug(myPlainText ); 
   
    // New Task object to be created
    Task[] newTask = new Task[0];
  
    // Try to look up any Leads based on the email from address
    // If there is more than one Lead with the same email address,
    // an exception will be thrown and the catch statement will be called.
    try {
    
        String  relatedRecordId = myPlainText.subStringAfter('RecordId:-');
        System.debug('Lead Id:' + relatedRecordId); 
          
        relatedRecordId = relatedRecordId.trim();
        relatedRecordId = relatedRecordId.substring(0,15);
    
      Lead vLead = [SELECT Id, Name, Email
        FROM Lead
        WHERE Id = : relatedRecordId
        LIMIT 1];
      
      // Add a new Task to the lead record we just found above.
      newTask.add(new Task(Description =  myPlainText,
           Priority = 'Normal',
           Status = 'Inbound Email',
           Subject = email.subject,
           WhoId = vLead.Id));
     
     // Insert the new Task 
     insert newTask;    
     
     System.debug('New Task Object: ' + newTask );   
    }
    // If an exception occurs when the query accesses 
    // the Lead record, a QueryException is called.
    // The exception is written to the Apex debug log.
   catch (QueryException e) {
       System.debug('Query Issue: ' + e);
   }
   
   // Set the result to true. No need to send an email back to the user 
   // with an error message
   result.success = true;
   
   // Return the result for the Apex Email Service
   return result;
  }
}


 
Om PrakashOm Prakash
You can verify the Email Service Email Address.
Thats why I have mentioned "You need to debug myPlainText in code after line number 13 then you can verify that email service after copy verification link from debug log."

Please clieck Resend in "Organization-Wide Email Addresses", then copy verification link from debug log.

Let me know if issue in this one time setup.

 
Om PrakashOm Prakash
Please ignore that Ending position out of bounds exception in this case.
You can find the "Click this link to confirm this Organization-Wide Email Address" in debug log.
Verify the email by using this link
Michael Hedrick 2Michael Hedrick 2
Thank for staying with this.  Did you see my previous post?  After resending the verification I do not see a log being created for the Apex Class but I think it is becasue the resend delivery is failing.
Om PrakashOm Prakash
I suggest add catch (Exception ex) {} after  catch (QueryException e) , so that Email Service don't fail in above exception case.
Then you can copy verification link from debug after resenindg from Organization-Wide Email Address.

Hope it works :)
Michael Hedrick 2Michael Hedrick 2
FINALLY!  Thank you for all your help.  I had chnged the 'Context User' to our integration user instead of myself so no emails where going to the Apex Class.  Not sure why, but I will post as a seperate question.
Thanks again for all of your help and patience.