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
ChickenOrBeefChickenOrBeef 

BCC-To-Salesforce doesn't run triggers?

Hey Everyone,

I have a task trigger that creates a bunch of records once a task is inserted. This trigger works fine when I manually create a task in Salesforce. But if we use the BCC-to-Salesforce address to log an email as a task, the trigger doesn't seem to run. I've tried manually creating tasks that have the same exact same values as the tasks created via BCC, and the manuallly created tasks will run the trigger while the BCC-created tasks do not.

Is there something I need to take into account? Does BCCing simply not support triggers?


Here is the class I'm testing:

public class ClassRelatedActivitiesInsert {
    
    public void insertRelatedActivities(List<Task> tasks){
        
        Set<String> accountsInTrigger = new Set<String>();
        Set<String> contactsInTrigger = new Set<String>();
        Set<String> parentSet = new Set<String>();
        Set<String> clientSet = new Set<String>();
        Set<String> agencySet = new Set<String>();
        Set<String> siblingAccounts = new Set<String>();
        
        Map<String,String> contactMap = new Map<String,String>();
        Map<String,String> parentMap = new Map<String,String>();
        Map<String,String> siblingParentMap = new Map<String,String>();
        Map<String,String> clientAgencyMap = new Map<String,String>();
        Map<String,String> agencyClientMap = new Map<String,String>();
        
        List<Account> childAccounts = new List<Account>();
        List<Client_Agency_Relationship__c> clientAgencies = new List<Client_Agency_Relationship__c>();
        List<Related_Activity__c> relatedActivitiesToAdd = new List<Related_Activity__c>();
        
        
    FOR(Task t : tasks){        
                IF(t.WhatId != NULL && string.valueOf(t.WhatId).startsWith('001')){
                    accountsInTrigger.add(t.WhatId);
                }
                ELSE IF(t.WhatId == NULL && t.WhoId != NULL && string.valueOf(t.WhoId).startsWith('003')){
                        contactsInTrigger.add(t.WhoId);
                    }       
        }
        
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after initial task loop is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after initial task loop is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        
        IF(contactsInTrigger.size() > 0){
            FOR(Contact c : [SELECT
                                Id,AccountId
                             FROM
                                Contact
                             WHERE
                                Id In :contactsInTrigger
                             AND
                              AccountId != NULL]){
                                 
                                     contactMap.put(c.Id,c.AccountId);
                                     accountsInTrigger.add(c.AccountId);
                                 
                                }
        }
        
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after account contacts SOQL is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after account contacts SOQL is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        
        IF(accountsInTrigger.size() > 0){
            FOR(Account ca : [SELECT 
                                 Id,ParentId
                              FROM 
                                 Account
                              WHERE
                                 ParentId In :accountsInTrigger
                              OR
                                 (ParentId != NULL
                              AND
                                  Id In :accountsInTrigger)]){
                                      
                                      IF(accountsInTrigger.contains(ca.ParentId)){
                                          childAccounts.add(ca);
                                      }
                                      IF(accountsInTrigger.contains(ca.Id) && ca.ParentId != NULL){
                                          parentMap.put(ca.Id,ca.ParentId);
                                          parentSet.add(ca.ParentId);
                                      }
                                      
                                  }
        }
        
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after parent/child account SOQL is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after parent/child account SOQL is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        
        IF(parentSet.size() > 0){
            FOR(Account sa : [SELECT
                                 Id, ParentId
                              FROM
                                 Account
                              WHERE
                                 ParentId In :parentSet]){
                                  
                                    siblingParentMap.put(sa.Id,sa.ParentId);
                                    siblingAccounts.add(sa.Id);
                                  
                                }
        }
        
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after sibling SOQL is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after sibling SOQL is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        
        IF(accountsInTrigger.size() > 0){
            clientAgencies = [SELECT
                                 Id,Client__c,Agency__c
                              FROM
                                 Client_Agency_Relationship__c
                              WHERE
                                 Client__c In :accountsInTrigger
                              OR
                                 Agency__c In :accountsInTrigger];
        }
        
        
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after clientAgencies SOQL is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after clientAgencies SOQL is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
            
        FOR(Task t0 : tasks){
            
            String accountID0;
            String parentID0;
                
                  IF(t0.WhatId != NULL){
                          accountID0 = t0.WhatId;
                          parentID0 = parentMap.get(t0.WhatId);
                    }
                                        
                    ELSE IF(t0.WhatId == NULL && t0.WhoId != NULL && contactMap.get(t0.WhoId) != NULL){
                          accountID0 = contactMap.get(t0.WhoId);
                          parentID0 = parentMap.get(contactMap.get(t0.WhoId));
                    }
        
            FOR(Account a : childAccounts){
                
                IF(a.ParentId == accountID0){
                    
                    Related_Activity__c ra0 = new Related_Activity__c();
                    
                    IF(t0.Subject.length() > 80){
                        ra0.Name = t0.Subject.SubString(0,80);
                    }
                    ELSE{
                        ra0.Name = t0.Subject;
                    }
                    
                    IF(t0.WhoId != NULL && string.valueOf(t0.WhoId).startsWith('003')){
                        ra0.Name__c = t0.WhoId;
                    }
                    
                        ra0.Date__c = t0.ActivityDate;
                        ra0.Description__c = t0.Description;
                        ra0.Assigned_To__c = t0.OwnerId;
                        ra0.Activity_ID__c = t0.Id;
                        ra0.Relationship__c = 'Parent';
                        ra0.Account__c = a.Id;
                        ra0.Related_To__c = accountID0;
                
                    relatedActivitiesToAdd.add(ra0);
                    
                }
                
            }
            
            FOR(String a1 : siblingAccounts){
                    
                    IF(siblingParentMap.get(a1) == parentID0 && a1 != accountID0){
                    
                    Related_Activity__c ra1 = new Related_Activity__c();
                        
                        IF(t0.Subject.length() > 80){
                            ra1.Name = t0.Subject.SubString(0,80);
                        }
                        ELSE{
                            ra1.Name = t0.Subject;
                        }
                        
                        IF(t0.WhoId != NULL && string.valueOf(t0.WhoId).startsWith('003')){
                          ra1.Name__c = t0.WhoId;
                      }
                        
                    ra1.Date__c = t0.ActivityDate;
                    ra1.Description__c = t0.Description;
                    ra1.Assigned_To__c = t0.OwnerId;
                  ra1.Activity_ID__c = t0.Id;
                    ra1.Name__c = t0.WhoId;
                    ra1.Relationship__c = 'Sibling';
                    ra1.Account__c = a1;
                    ra1.Related_To__c = accountID0;
                    
                    relatedActivitiesToAdd.add(ra1);
                        
                    }
                }
            
            FOR(Client_Agency_Relationship__c car0 : clientAgencies){
                
                IF(car0.Agency__c == accountID0){
                
                    Related_Activity__c ra2 = new Related_Activity__c();
                    
                    IF(t0.Subject.length() > 80){
                        ra2.Name = t0.Subject.SubString(0,80);
                    }
                    ELSE{
                        ra2.Name = t0.Subject;
                    }
                    
                    IF(t0.WhoId != NULL && string.valueOf(t0.WhoId).startsWith('003')){
                          ra2.Name__c = t0.WhoId;
                      }
                    
                    ra2.Date__c = t0.ActivityDate;
                    ra2.Description__c = t0.Description;
                    ra2.Assigned_To__c = t0.OwnerId;
                    ra2.Activity_ID__c = t0.Id;
                    ra2.Relationship__c = 'Agency';
                    ra2.Account__c = car0.Client__c;
                    ra2.Related_To__c = accountID0;
                
                    relatedActivitiesToAdd.add(ra2);
                    
                }
            }
            
            FOR(Client_Agency_Relationship__c car1 : clientAgencies){
                
                IF(car1.Client__c == accountID0){
                
                    Related_Activity__c ra3 = new Related_Activity__c();
                    
                    IF(t0.Subject.length() > 80){
                        ra3.Name = t0.Subject.SubString(0,80);
                    }
                    ELSE{
                        ra3.Name = t0.Subject;
                    }
                    
                    IF(t0.WhoId != NULL && string.valueOf(t0.WhoId).startsWith('003')){
                          ra3.Name__c = t0.WhoId;
                      }
                    
                    ra3.Date__c = t0.ActivityDate;
                    ra3.Description__c = t0.Description;
                    ra3.Assigned_To__c = t0.OwnerId;
                    ra3.Activity_ID__c = t0.Id;
                    ra3.Relationship__c = 'Client';
                    ra3.Account__c = car1.Agency__c;
                    ra3.Related_To__c = accountID0;
               
                    relatedActivitiesToAdd.add(ra3);
                    
                }
            }
            
            FOR(String a4 : parentSet){
                
                IF(parentID0 == a4){
                
                    Related_Activity__c ra4 = new Related_Activity__c();
                    
                    IF(t0.Subject.length() > 80){
                        ra4.Name = t0.Subject.SubString(0,80);
                    }
                    ELSE{
                        ra4.Name = t0.Subject;
                    }
                    
                    IF(t0.WhoId != NULL && string.valueOf(t0.WhoId).startsWith('003')){
                          ra4.Name__c = t0.WhoId;
                      }
                    
                    ra4.Date__c = t0.ActivityDate;
                    ra4.Description__c = t0.Description;
                    ra4.Assigned_To__c = t0.OwnerId;
                    ra4.Activity_ID__c = t0.Id;
                    ra4.Relationship__c = 'Child';
                    ra4.Account__c = a4;
                    ra4.Related_To__c = accountID0;
               
                    relatedActivitiesToAdd.add(ra4);
                    
                }
          }
       
      } 
           
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after related activities creation is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after related activities creation is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        
        
        IF(relatedActivitiesToAdd.size() > 0){
          INSERT relatedActivitiesToAdd;
        }
        
        System.debug(LoggingLevel.ERROR,'INSERT: Heap size after trigger completion is ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
        System.debug(LoggingLevel.ERROR,'INSERT: CPU time after trigger completion is ' + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        
    }

}

And here is our task trigger, which calls all the classes:

trigger MainTriggerTask on Task (after insert, after update) {
    
    IF(Trigger.IsAfter){
        IF(Trigger.IsInsert){
            
            if(checkRecursive.runAfterInsertOnce()){
                
                ClassLeadContacted updater = new ClassLeadContacted();
                updater.updateLastContacted(Trigger.new);
                
                ClassLibraryTaskEmail updater1 = new ClassLibraryTaskEmail();
                updater1.sendEmail(Trigger.new);
                
                ClassRelatedActivitiesInsert updater2 = new ClassRelatedActivitiesInsert();
                updater2.insertRelatedActivities(Trigger.new);
                
            }
        }
        IF(Trigger.IsUpdate){
            
            if(checkRecursive.runAfterUpdateOnce()){
                
                ClassLeadContacted updater1 = new ClassLeadContacted();
                updater1.updateLastContacted(Trigger.new);
                
                ClassRelatedActivities updater2 = new ClassRelatedActivities();
                updater2.addRelatedActivities(Trigger.new,Trigger.oldMap);
                
                ClassTaskUpdateRelatedActivity updater3 = new ClassTaskUpdateRelatedActivity();
                updater3.updateRelatedActivity(Trigger.new,Trigger.oldMap);
                
            }
        }
    }
}

Let me know if you need any other info from me.

Thanks!
-Greg


Best Answer chosen by ChickenOrBeef
ChickenOrBeefChickenOrBeef
Hey Vi5h,

It turns out that BCC'd emails weren't running the trigger since BCC'd email tasks don't have WhoID populated upon creation. So I'll have to push most of the code to a future method.

Thanks for your help!
-Greg

All Answers

Vi5hVi5h
Hi Greg,

On a quick look at the trigger code, i suspect there is something in the checkRecursive.runAfterInsertOnce() that is not right, can you please post the code here, if you debug out the statements, do you see the entry point for the trigger and your class methods

Ta

Vish
ChickenOrBeefChickenOrBeef
Hey Vi5h,

Sorry for the delayed response, but here's the recursion class you wanted to see:

public class checkTaskRecursive {
    
    private static boolean runBeforeInsert = true;
    private static boolean runBeforeUpdate = true;
    private static boolean runBeforeDelete = true;
    private static boolean runAfterInsert = true;
    private static boolean runAfterUpdate = true;
    private static boolean runAfterDelete = true;
    
    public static boolean runBeforeInsertOnce(){
        
    if(runBeforeInsert){
     runBeforeInsert = false;
     return true;   
    }
    else{
        return runBeforeInsert;
    }
        
    }
    
    public static boolean runBeforeUpdateOnce(){
        
    if(runBeforeUpdate){
     runBeforeUpdate = false;
     return true;   
    }
    else{
        return runBeforeUpdate;
    }
        
    }
    
    public static boolean runBeforeDeleteOnce(){
        
    if(runBeforeDelete){
     runBeforeDelete = false;
     return true;   
    }
    else{
        return runBeforeDelete;
    }
        
    }
    
    public static boolean runAfterInsertOnce(){
        
    if(runAfterInsert){
     runAfterInsert = false;
     return true;   
    }
    else{
        return runAfterInsert;
    }
        
    }
    
    public static boolean runAfterUpdateOnce(){
        
    if(runAfterUpdate){
     runAfterUpdate = false;
     return true;   
    }
    else{
        return runAfterUpdate;
    }
        
    }
    
    public static boolean runAfterDeleteOnce(){
        
    if(runAfterDelete){
     runAfterDelete = false;
     return true;   
    }
    else{
        return runAfterDelete;
    }
        
    }

}

I was using the "checkRecursive" class for both my Account trigger and my Task trigger, so I copied the class and made one specific for the Task trigger called "checkTaskRecurisve". I thought that might have something to do with the issue, but the issue still occurs.

I tried removing the recursion check and testing the code, but removing the recursion check gives me the "too many SOQL queries: 101" error.

But anywho, let me know if you spot anything wrong with that code, or if there's anything else I should test on my end.

Thanks,
Greg
ChickenOrBeefChickenOrBeef
Hey Vi5h,

It turns out that BCC'd emails weren't running the trigger since BCC'd email tasks don't have WhoID populated upon creation. So I'll have to push most of the code to a future method.

Thanks for your help!
-Greg
This was selected as the best answer
Thomas Graves 1Thomas Graves 1
I'm having this problem as well. It appears that Tasks created from bcc to salesforce do not get a whatID... if anyone finds a solution please let me know.
ChickenOrBeefChickenOrBeef
Hey Thomas,

Check out the Best Answer marked above. You have to use a "Future Method". Gather your records into a list and then push that list into a future method, which will run after the tasks receive their WhatID and/or WhoID.

If you need more info, let me know.

-Greg
Thomas Graves 1Thomas Graves 1
Hey Greg,

Thanks for the response. At what point do the tasks receive their WhatIds/WhoIds other than manually adding an Account/Contact?
 
ChickenOrBeefChickenOrBeef
I'm not sure exactly when, but I know that BCC'd tasks don't have a WhatID/WhoID upon creation. It happens probably a second later. If you use a Future Method, your code will be running after the WhatID/WhoID has been populated. So if your code depends on what's in those fields, you'll have to do that. Sorry I'm not more specific.