One of the Salesforce powerful feature is Inbound Email
Services. Using this, you can send an email to Salesforce and process the email
body as you want. Inbound email handler class allows you to access email’s
plain text body as well as html body.
One issue that I came across was, none of the existing
method can handle your inbound email’s inline images. I searched community a
lot and realized that, too many people had the same issue but they never find
any solution, so I thought to pick it from there.
Issue:
You want to write email’s HTML body in a Rich Text area
field and your email has inline images. Now, when you send this, inbound email
will lost those images references and your body will say “Inline Image XXXXX”.
More Detail:
I have created an email service in my org. It only listens
inbound email and put the email’s HTML body in a rich text area field on lead.
global class POCEmailHandler implements Messaging.InboundEmailHandler { //Method to process email global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) { Messaging.InboundEmailResult result = new Messaging.InboundEmailresult(); //Create a New Lead record Lead lead = new Lead(); lead.LastName = 'Inbound Lead'; lead.Email = email.fromAddress; lead.Company = 'N/A'; lead.HTML_Body__c = email.htmlBody; //Insert record insert lead; } }
Now I sent below email to this email service. Inbound
handler class processed it and a new lead was created in system.
This lead was created in system. Notice the HTML Body field.
Inline image didn’t came in the HTML body.
Reason:
Salesforce process inline images as binary attachments. When
you send an email having inline images, it doesn’t come as a part of body, but
it comes as binary attachment. From here, you will have to put your own logic
to place the inline images back in HTML Body.
Resolution:
1.
Process binary attachments and see, which
attachment came as a part on inline image. Create an attachment record for each
image. Below code is to create a map with the inline image name and its related
attachment record.
//Create a list of attachments Map< String, Attachment > mapAttachments = new Map< String, Attachment >(); //Attachments for(Messaging.InboundEmail.BinaryAttachment bA : email.binaryAttachments) { System.debug(bA); for(integer i = 0; i < bA.headers.size(); i++) { //Header Value String headerValue = bA.headers[i].value; if(headerValue.startsWith('ii') || headerValue.startsWith('< image')) { headerValue = headerValue.replaceAll('<', '').replaceAll('>', ''); mapAttachments.put(headerValue, new Attachment(Name = bA.fileName, body = bA.body, ParentId = lead.Id, ContentType = bA.mimeTypeSubType)); } } }
2.
Now process HTML body content and get all the
places where actual Inline Image was replaced with blank space and update these
instances with the attachment link.
//Process inline images and update the HTML Body for(String headerValue : mapAttachments.keySet()) { //Reference Link String refLink = '/servlet/servlet.FileDownload?file=' + mapAttachments.get(headerValue).Id; lead.HTML_Body__c = lead.HTML_Body__c.replaceAll('cid:' + headerValue, refLink); } update lead;
Updated code will look like this.
global class POCEmailHandler implements Messaging.InboundEmailHandler { global class POCEmailHandler implements Messaging.InboundEmailHandler { //Method to process email global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) { Messaging.InboundEmailResult result = new Messaging.InboundEmailresult(); //Create a New Lead record Lead lead = new Lead(); lead.LastName = 'Inbound Lead'; lead.Email = email.fromAddress; lead.Company = 'N/A'; lead.HTML_Body__c = email.htmlBody; //Insert record insert lead; //Create a list of attachments Map< String, Attachment > mapAttachments = new Map< String, Attachment >(); //Attachments for(Messaging.InboundEmail.BinaryAttachment bA : email.binaryAttachments) { System.debug(bA); for(integer i = 0; i < bA.headers.size(); i++) { //Header Value String headerValue = bA.headers[i].value; if(headerValue.startsWith('ii') || headerValue.startsWith('< image')) { headerValue = headerValue.replaceAll('<', '').replaceAll('>', ''); mapAttachments.put(headerValue, new Attachment(Name = bA.fileName, body = bA.body, ParentId = lead.Id, ContentType = bA.mimeTypeSubType)); } } } //Insert insert mapAttachments.values(); //Process inline images and update the HTML Body for(String headerValue : mapAttachments.keySet()) { //Reference Link String refLink = '/servlet/servlet.FileDownload?file=' + mapAttachments.get(headerValue).Id; lead.HTML_Body__c = lead.HTML_Body__c.replaceAll('cid:' + headerValue, refLink); } update lead; return result; } }
Now send the same email to Salesforce email address and see
the result.