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
Abby StockerAbby Stocker 

Help replicating email to case feed item for Custom Object

Hello! We have custom email functionality built for a custom object, "Delivery Exceptions". This email functionality replicates that of email to case as in you send an email out with the exception reference number and the replies will attach to the approriate record and each has an email message related list to store them. I have an ask that these emails ALSO come into the exception chatter feed just like they do for email to case. Here is what the emails look like now in the chatter feed:
User-added imageHere is what they look like in Case:
User-added imageHow can I make fix the code to accomplish this? They also want the ability to reply/forward from the chatter post as well like you can with email to case. Any help is GREATLY appreciated. Thank you! 

Here is the code as it stands:

global class DeliveryEmailHandler implements Messaging.InboundEmailHandler {
    global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
        Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
            id deliveryexceptionId;
            string emailBody = email.plainTextBody;        
            string deliveryexceptionName ='';
            string emailSubject= email.subject;
            system.debug('email subject'+emailSubject);
            pattern regEx = Pattern.compile('(E[0-9]{8})');
            matcher deliveryexceptionMatcherSubject = regEx.matcher(emailSubject);
            if(deliveryexceptionMatcherSubject.find() && != null){
                deliveryexceptionName =;
                system.debug('Delivery Exception name found in subject');
            } else {
                // try body of email if not in subject
                matcher deliveryexceptionMatcherBody = regEx.matcher(emailBody);
                if(deliveryexceptionMatcherBody.find() && != null){
                    deliveryexceptionName =;
                    system.debug('Delivery Exception name found in body');
            // if matcher matches find delivery exception record
            If (deliveryexceptionName != ''){
                list<Delivery_Exception__c> deliveryexceptionList = [select id,name,account__c from Delivery_Exception__c where name = :deliveryexceptionName];
                if(!deliveryexceptionList.isEmpty() && deliveryexceptionList.size() == 1){
                    deliveryexceptionId = deliveryexceptionList[0].id;
            // attach to error delivery exception if no delivery exception record is found
            if(deliveryexceptionId == null){
                deliveryexceptionId = [select id from Delivery_Exception__c where external_id__c = 'ERROR' limit 1].Id;
            EmailMessage cEmailMessage = new EmailMessage();
            cEmailMessage.ToAddress =  String.join(email.toAddresses, ',');
            cEmailMessage.FromAddress = email.FromAddress;
            cEmailMessage.FromName = email.FromName;
            cEmailMessage.Subject = email.subject;
            cEmailMessage.status = '0';
            cEmailMessage.HtmlBody = email.htmlBody;
            //System.debug('htmlBody:>>>> ' + email.htmlBody );
            cEmailMessage.Incoming= True;
            cEmailMessage.TextBody = email.plainTextBody;
            cEmailMessage.relatedToId = deliveryexceptionId;
            cEmailMessage.Delivery_Exception__c = deliveryexceptionId;
            //cEmailMessage.validatedFromAddress = '';
            //System.debug('TextBody:>>>>> ' + email.plainTextBody);
            insert cEmailMessage;
            FeedItem item = new FeedItem();
            item.parentId = cEmailMessage.relatedToId = deliveryexceptionId;
            item.Body = cEmailMessage.relatedToId = deliveryexceptionId;
            insert item;
            System.debug('Reply Email: ' + cEmailMessage ); 
            //Add Email Message Relation the from address
            list<emailMessageRelation> emailMessageRelations = new list<emailMessageRelation>();
            emailMessageRelations.add(new EmailMessageRelation(
                EmailMessageId =,
                RelationAddress = email.FromAddress,
                RelationType = 'FromAddress'));
            // as of 10-24-19 Salesforce required a relationship to be able to reply.
            // this code section can be removed when Salesforce support Org Wide Email Addresses to be used on custom objects
            // with the functionality supported on the case object.
            for(user u : [select id,email from user where Exception_Email_Functionality__c = true and isactive = true]){
                emailMessageRelations.add(new EmailMessageRelation(EmailMessageId =, RelationId =, RelationType = 'BccAddress'));    
            insert emailMessageRelations;
            // if email attachments are not null create files
            if(email.binaryAttachments != null) createContentDocumentLinks(email.binaryAttachments,, deliveryexceptionId);
        } catch(exception e){
            system.debug('exception processing delivery exception inbound email:'+e.getMessage());
        result.success = true;
        return result;
    public boolean createContentDocumentLinks(Messaging.InboundEmail.BinaryAttachment[] binAttachList, Id insertedEmailMessageId, Id deliveryexceptionId) {
        List<ContentVersion>cvList = new List<ContentVersion>();
        List<ContentDocumentLink> cdlList = new List<ContentDocumentLink>();
        for (Messaging.InboundEmail.BinaryAttachment binAttach : binAttachList) {
            ContentVersion testContentInsert = new ContentVersion();
            testContentInsert.Title = binAttach.fileName;
            testContentInsert.VersionData = binAttach.body;
            testContentInsert.PathOnClient = '/' + binAttach.fileName ;
        insert cvList;
        cvList = [select id, ContentDocumentId from ContentVersion WHERE Id in :cvList];
        for (ContentVersion cv : cvList) {
            ContentDocumentLink cl = new ContentDocumentLink();
            cl.ContentDocumentId = cv.ContentDocumentId;
            cl.LinkedEntityId = insertedEmailMessageId;
            cl.ShareType = 'V';
            cl.Visibility = 'AllUsers';
            // add link to delivery exception also
            ContentDocumentLink clc = new ContentDocumentLink();
            clc.ContentDocumentId = cv.ContentDocumentId;
            clc.LinkedEntityId = deliveryexceptionId;
            clc.ShareType = 'V';
            clc.Visibility = 'AllUsers';
        insert cdlList;
        return true;