Discovered this recently because a trigger was failing when triggered by a community user. Can't figure out why this should matter though, with the apex running in system mode and all. Is this specific to the Messaging class in some way?

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>{'joe@aol.com'});

                    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);


  • 2
    "System mode" doesn't bypass all the rules of the system. Notably, the generic "insufficient access on cross-reference id" error (which I presume you're getting) can mean that a record can't be created because it would create sharing entries that grant access to a record the user shouldn't have access to. We'd need more specific details in order to help you out with your inquiry. Code, sharing model, etc, would all be good places to start. – sfdcfox Dec 10 '19 at 4:33
  • Thanks, full story and code is located here: salesforce.stackexchange.com/questions/287595/… - it is creating an email alert when feed comments are made, and you are correct in that “insufficient access on cross reference ID“ was thrown, because community users did not have access to the user objects. But why should that be necessary? The email is not being sent from or to any community user. – number41 Dec 11 '19 at 5:47
  • Hi sfdcfox, if you know, I’m still really curious why the running user requires access to the user object for this. The code is in the link above. Any idea? I can’t find anything on it, and it doesn’t seem to make much sense. I’m not sure what you mean by “sharing entries could be created” - in my case, an email is simply being sent from an org wide email address, which seemingly has nothing to do with the running user. Thanks – number41 Dec 21 '19 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.