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
SF_Admin96SF_Admin96 

How to create Opportunity from Incoming Email using Email Services

Hi All,

I hope you could assist me in achieving my goal here. I am not a coder and just following the patterns on existing codes anywhere in the site. My goals are:
  • Create Opportunity record from incoming emails. (create something like e2c)
  • Create Contact record if there are no matching emails in the system and populate the custom Contact lookup in Opp.
  • When user send an email from that Opportunity record and customer replies back, the response should be attached to existing Opportunity.
Here's what I have:
  • Custom Contact Lookup in Opportunity
  • ThreadID field in Opportunity which I use in Email Subject and Description:

Here is the existing code:

global class OpportunityCreation implements Messaging.InboundEmailHandler {

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

     Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
    
       Contact vCon = [Select Id, Name, Email, AccountId
       From Contact 
       Where Email = :email.fromAddress
       Limit 1];

    Opportunity opportunity = new Opportunity();
    opportunity.Name = email.Subject;
    opportunity.StageName = 'Prospecting';
    opportunity.CloseDate = Date.today();
    opportunity.Email_Body__c = email.plainTextBody;
    opportunity.Contact_Name__c = vCon.Id;
    opportunity.AccountId = vCon.AccountId;
    insert opportunity;
    
       System.debug('====> Created opportunity '+opportunity.Id);
       
      
if (email.binaryAttachments != null && email.binaryAttachments.size() > 0) {
      for (integer i = 0 ; i < email.binaryAttachments.size() ; i++) {
        Attachment attachment = new Attachment();
        // attach to the newly created opportunity record
        attachment.ParentId = opportunity.Id;
        attachment.Name = email.binaryAttachments[i].filename;
        attachment.Body = email.binaryAttachments[i].body;
        insert attachment;
      }
    }
  
    return result;

  }

}

Current behavior of the code:
  • It doesn't create an Opportunity if there are no matching email address in the system. (Expected: create Opportunity + Contact if there are no matching email in the system)
  • Email Threads like email to case doesn't work.
Any assistance is greatly appreciated.

  •  
AshwaniAshwani
Can you debug you code by enclosing it into try catch. I suspect there is an error.
AshlekhAshlekh
Hi 

Hope below code helps you 
global class OpportunityCreation implements Messaging.InboundEmailHandler {

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

     Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
    
     Contact vCon;
	 for(Contact c: [Select Id, Name, Email, AccountId From Contact Where Email = :email.fromAddress Limit 1])
	     vCon = c;
     if(vCon == null)
     {
		vCon = new Contact(lastname = 'Your name',email = email.fromAddress);
		insert vCon;
	 }	 
	 
     Opportunity opportunity = new Opportunity();
     opportunity.Name = email.Subject;
     opportunity.StageName = 'Prospecting';
     opportunity.CloseDate = Date.today();
     opportunity.Email_Body__c = email.plainTextBody;
     opportunity.Contact_Name__c = vCon.Id;
     opportunity.AccountId = vCon.AccountId;
     insert opportunity;
    
       System.debug('====> Created opportunity '+opportunity.Id);
       
      
if (email.binaryAttachments != null && email.binaryAttachments.size() > 0) {
      for (integer i = 0 ; i < email.binaryAttachments.size() ; i++) {
        Attachment attachment = new Attachment();
        // attach to the newly created opportunity record
        attachment.ParentId = opportunity.Id;
        attachment.Name = email.binaryAttachments[i].filename;
        attachment.Body = email.binaryAttachments[i].body;
        insert attachment;
      }
    }
  
    return result;

  }

}
IF it helps you than please mark it as a solution and ENJOY APEX
SF_Admin96SF_Admin96
Hi Ashlekh,

It works great!! However, when a customer replies to the email sent FROM Opportunity record (with threadID), it is not being attached to existing Opportunity, instead, new Opportunity is being created. 

My goal is to have the same functionality on Case that when we send an email, it will have a threadID and when the customer reply back, it will be attached to existing Opportunity. I have no problems sending with ThreadId. But I am having problems parsing ThreadId in the email body. What should be added on the code.

Thanks again Ashlekh!
Steven DowneySteven Downey
Afternoon,
this code is great and has been a big help, well in our sandbox anyway, im at the stage of transferring this to production, to transfer this code how would we do the test class? or do we not need one to transfer this?

Many thanks
Steve
Sam LauSam Lau
I know this is an older thread, but I'm trying to identify a way to attach replies to an existing record instead of it creating a new.  Any assistance would be helpful.