FeedItem trigger that sends email fails only for communities users

We have Apex sending emails to users when certain chatter feed posts are made, and it seems to be working fine for regular users in production, but we are hitting this error when customer community users make any kind of feed post:

23:56:28:248 FATAL_ERROR System.EmailTemplateRenderException:
INVALID_CROSS_REFERENCE_KEY: invalid cross reference id

The line it is failing on is:

mail = Messaging.renderStoredEmailTemplate(templateId, userEmailIdMap.get(email).Id, f.Id);

The developers who wrote the code did not write real tests for it, so it’s a bit difficult to debug. Do chatter feed posts operate fundamentally different in communities?

trigger FeedItemTrigger on FeedItem (after insert) {

    if(Trigger.isInsert && Trigger.isAfter){

        Set<Id> setOppId = new Set<Id>();
        Map<Id,FeedItem> mapOppIdToFeedItemId = new Map<Id,FeedItem>();

        for(FeedItem f : Trigger.New) {

        List<Opportunity> oppToUpdate = new List<Opportunity>();
        List<Opportunity> oppList = [SELECT Last_Chatter_Post__c FROM Opportunity WHERE Id IN: mapOppIdToFeedItemId.keySet()];

        for(Opportunity opp : [SELECT Last_Chatter_Post__c FROM Opportunity WHERE Id IN: mapOppIdToFeedItemId.keySet()]){
            FeedItem item = mapOppIdToFeedItemId.get(opp.Id);
            String items = item.Body.replaceAll('<[/a-zAZ0-9]*>','');
            items += 'n Created By: '+ UserInfo.getFirstName() + ' ' +UserInfo.getLastName();
            opp.Last_Chatter_Post__c = items;

        update oppToUpdate;

        List<String> toAddresses = new List<String>();

        List<Feed_Item_Setting__mdt> recipientList = [SELECT MasterLabel, QualifiedApiName, User_Email__c FROM Feed_Item_Setting__mdt Limit 200];
        for (Feed_Item_Setting__mdt recipient : recipientList) {

            if(recipient.User_Email__c != null){

        //Stores user email / Id 
        Map<String, User> userEmailIdMap = new Map<String, User>(); 

        if(toAddresses.size() >0){
                for(User u : [Select Email, FirstName, LastName, Id From User where Email IN: toAddresses]){
                        userEmailIdMap.put(u.Email, u);
            }catch(Exception e){
                system.debug('Error getting user info ' + e.getMessage());

        //Get email template name 
        List<Email_Template__mdt> emailTemplateName = [SELECT MasterLabel, QualifiedApiName FROM Email_Template__mdt Where MasterLabel = 'Feed Item' Limit 1];

        EmailTemplate objCaseTemplate;
        EmailTemplate objTemplate;
        if(emailTemplateName.size() > 0){
            for(EmailTemplate objTemp : [SELECT Id, Subject, HtmlValue, Body, DeveloperName FROM EmailTemplate WHERE (DeveloperName =: emailTemplateName[0].QualifiedApiName OR DeveloperName = 'ChatterPostNotifyVF_Case')]){
                if(objTemp.DeveloperName == emailTemplateName[0].QualifiedApiName){
                    objTemplate = objTemp;
                    objCaseTemplate = objTemp;

        for(FeedItem f : Trigger.New) {

            //Create email
            List<Messaging.SingleEmailMessage> theEmails = new List<Messaging.SingleEmailMessage>();

            for(String email : toAddresses){


                    //Create email
                    Messaging.SingleEmailMessage mail; 
                    if(objTemplate != null || objCaseTemplate != null){
                        //template id, whoId, WhatId
                        String templateId = (String.valueOf(f.parentId).startsWith('500')?objCaseTemplate.Id:objTemplate.Id);
                        mail = Messaging.renderStoredEmailTemplate(templateId, userEmailIdMap.get(email).Id, f.Id);
                            mail.setToAddresses(new List<String>{'<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c0603092c0d0300420f0301">[email protected]</a>'});

                        mail = new Messaging.SingleEmailMessage();
                        mail.setSubject('New Chatter Post');

                    //The ID of the contact, lead, or user to which the email will be sent
                    //Specifying the user ID in setTargetObjectId means the email doesn’t count toward the daily limit. 

                    //saveAsActivity must be false when sending mail to users


            String emailErrorReport = '';

            //Send Email
                Messaging.SendEmailResult[] results = Messaging.sendEmail( theEmails );

                for( Messaging.SendEmailResult currentResult : results ) {
                    for( Messaging.SendEmailError currentError : currentResult.getErrors() ) {
                        emailErrorReport = emailErrorReport + '(' + currentError.getStatusCode() + ') ' + currentError.getMessage() + 'r' ;

                system.debug('Email Error Report ---> ' + emailErrorReport);


Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Discovered thanks to Pranay that Messaging.renderStoredEmailTemplate requires the running user to have object level access to the User object.

Only question is – why?

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Notify of

Inline Feedbacks
View all comments
Would love your thoughts, please comment.x