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
Jack Davis 3Jack Davis 3 

Additional Contacts to Email

Hi all, 

We created a custom object and have code that will email the related contacts with a defined role. We're wanting to expand this to include another role but also send a different template altogether. The prerequisite is when the record has a specific value. Here's the code I've created. Any help would be most appreciated. 

User-added image

User-added image
monsterloomismonsterloomis
Hi Jack,

A suggestion - can you update and use the "<>" (Add a code sample) in the top of the box? That will make it easier for folks to copy/paste, and for us 40+ developers - to read. :-) 

Dave
Jack Davis 3Jack Davis 3
Hi Dave

Hopefully this works

"< // set contacts (ClosedLoop Contacts) to be Closed Loop email recipients
                    List<Id> closedLoopEmailRecipientsIds = new List<Id>();                 
                    List<Contact> closedLoopContacts  = accountContactMap.get(accountId);
                    system.debug('closedLoopContacts: ' + closedLoopContacts);
                    for(Contact c : closedLoopContacts){ 
                        closedLoopEmailRecipientsIds.add(c.Id);
                        system.debug('closedLoopContact: ' + c.Name + ' ' + c.Email); 
                    } 
                    
                    // add the BDM as a BDM notice recipient
                    List<Id> bdmEmailRecipientsIds = new List<Id>();
                    Account dealerAccount = [select OwnerId, Owner.Name from Account where Id = :accountId];        // TODO remove query in loop
                    Id bdmId = dealerAccount.OwnerId;
                    system.debug('BDM : ' + bdmId);
                    bdmEmailRecipientsIds.add(bdmId);

                    // find the OrgWideEmailAddress (BDM) to send emails from (match BDM name to OrgWideEmailAddress name)
                    // if no match is found, leave blank, and the default system sender appears as the sender of the email
                    Id bdmSender;
                    if(BDMsendingAddresses != null){
                        for(OrgWideEmailAddress BDMsendingAddress : BDMsendingAddresses){
                            if(BDMsendingAddress.DisplayName == dealerAccount.Owner.Name) bdmSender = BDMsendingAddress.Id;
                        }
                    }

                    // check if sending process is overridden for testing
                    try{
                        
                        // override recipients with CustomSetting
                        Map<String, Closed_Loop_Config__c> closedLoopConfig = Closed_Loop_Config__c.getAll();
                        if(closedLoopConfig.containsKey('ClosedLoopEmailOverride_ContactEmails')){
                            Closed_Loop_Config__c config = closedLoopConfig.get('ClosedLoopEmailOverride_ContactEmails');
                            if(config.Value__c != null){
                                system.debug('OVERRIDING CLOSED LOOP EMAIL RECIPIENTS WITH ' + config.Value__c);
                                List<String> emailAddresses = config.Value__c.split(';');
                                List<Contact> overrideContacts = new List<Contact>();
                                if (this.isBounceManagementActivated()) {
                                    overrideContacts = [SELECT Id, Name, Email FROM Contact WHERE Email IN :emailAddresses AND EmailBouncedReason = null];
                                } else {
                                    overrideContacts = [SELECT Id, Name, Email FROM Contact WHERE Email IN :emailAddresses];
                                }
                                Map<String, Id> emailToId = new Map<String, Id>();
                                for(Contact c : overrideContacts) {
                                    emailToId.put(c.Email, c.Id);   // ensures we only send one email per override email address (locates 1 Contact even if many share the email address)
                                }
                                closedLoopEmailRecipientsIds = new List<Id>();  // reset list
                                for(String email : emailToId.keySet()){
                                    closedLoopEmailRecipientsIds.add(emailToId.get(email));
                                }
                            }
                        }
                        
                        
                        if(closedLoopConfig.containsKey('BDMEmailOverride_UserNames')){
                            Closed_Loop_Config__c config = closedLoopConfig.get('BDMEmailOverride_UserNames');
                            if(config.Value__c != null){
                                system.debug('OVERRIDING BDM EMAIL RECIPIENTS WITH ' + config.Value__c);
                                List<String> userNames = config.Value__c.split(';');
                                List<User> overrideUsers = [select Id, UserName, Email from User where UserName in :userNames];
                                bdmEmailRecipientsIds = new List<Id>(); // reset list
                                for(User u : overrideUsers){
                                    bdmEmailRecipientsIds.add(u.Id);
                                }
                            }
                        }
                    }
                    catch (Exception ex){
                        // ignore issues finding CustomSettings as it may not exist
                    }
                    // end of checking if sending process is overridden
                    
                    
                    // create Dealer Notification emails to Contacts
                    for(Id recipientId : closedLoopEmailRecipientsIds){
                        Messaging.SingleEmailMessage contactEmail = new Messaging.SingleEmailMessage();
                        contactEmail.setSaveAsActivity(false);
                        contactEmail.setTemplateId(template.Id);
                        contactEmail.setWhatId(cl.Id);
                        contactEmail.setTargetObjectId(recipientId);
                        if(bdmSender != null) contactEmail.setOrgWideEmailAddressId(bdmSender);
                        emails.add(contactEmail);
                    }
                    
                    // 24/08/15 JD: Where the notification account owner is John Shorthouse and the VM scheme is Hyundai, can we include Hyundai�s Area manager to receive the notifications?
                    if(dealerAccount.Owner.Name == 'John Shorthouse' && cl.Vehicle_Manufacturer__c == 'Hyundai'){
                        Messaging.SingleEmailMessage contactEmail = new Messaging.SingleEmailMessage();
                        contactEmail.setSaveAsActivity(false);
                        contactEmail.setTemplateId(template.Id);
                        contactEmail.setWhatId(cl.Id);
                        contactEmail.setTargetObjectId(hyundaiAreaManager.Id);
                        if(bdmSender != null) contactEmail.setOrgWideEmailAddressId(bdmSender);
                        emails.add(contactEmail);
                    }   
                    
                    // 24/08/15 JD: Land Rover notifications would like their aftersales director copied in.
                    if(cl.Insurance_Program__c == 'Land Rover' && cl.Notification_Type__c == 'Written Off'){
                        Messaging.SingleEmailMessage contactEmail = new Messaging.SingleEmailMessage();
                        contactEmail.setSaveAsActivity(false);
                        contactEmail.setTemplateId(template.Id);
                        contactEmail.setWhatId(cl.Id);
                        contactEmail.setTargetObjectId(landRoverAfterSalesDirector.Id);
                        if(bdmSender != null) contactEmail.setOrgWideEmailAddressId(bdmSender);
                        emails.add(contactEmail);
                    }
                    
                    
                    // create BDM email
                    for(Id recipientId : bdmEmailRecipientsIds){
                        Messaging.SingleEmailMessage bdmEmail = new Messaging.SingleEmailMessage();
                        bdmemail.setSubject('DEALER NOTIFICATION: Dealer ' + cl.Dealer_Name__c + ' was notified about ' + cl.Notification_Type__c + ' in ' + cl.Insurance_Program__c + ' insurance program.');
                        bdmemail.setPlainTextBody(getBDMEmailBody(cl));
                        bdmemail.setTargetObjectId(recipientId);
                        if(bdmSender != null) bdmemail.setOrgWideEmailAddressId(bdmSender);
                        bdmemail.setSaveAsActivity(false);
                        emails.add(bdmEmail);
                    }
                    
                    
                } else {
                    String errorMessage = 'Closed Loop: ' + cl.Id + ' - could not create emails as Account ' + accountId + ' does not have a Closed Loop Contact managing the Insurance Program ' + cl.Insurance_Program__c;
                    system.debug(errorMessage);
                    errorMessageUpdate.put(cl.Id, errorMessage);
                }
                
            }
            
            if(!errorMessageUpdate.isEmpty()){
                updateClosedLoopWithErrors(errorMessageUpdate);
            }
                
            return emails;
        }
        
        private void updateClosedLoopWithErrors(Map<Id, String> errorMessageUpdate){
            List<Closed_Loop__c> closedLoopRecordsToUpdate = new List<Closed_Loop__c>();
            for(Id closedLoopId : errorMessageUpdate.keySet()){
                // find in ClosedLoopCollection
                for(Closed_Loop__c cl : closedLoopCollection){
                    if(cl.Id == closedLoopId){
                        // add error to setup errors and add record to update collection
                        String clError = cl.Automatic_Setup_Errors__c;
                        clError = clError + '\n\n' + errorMessageUpdate.get(cl.Id);
                        cl.Automatic_Setup_Errors__c = clError;
                        closedLoopRecordsToUpdate.add(cl);
                    }
                }
            }
            if(closedLoopRecordsToUpdate.size() > 0){ update closedLoopRecordsToUpdate; }
        }
>"
monsterloomismonsterloomis
Thanks Jack - definitely more legible by far! I was referring to the little button with < > on it at the top of the comment box, which formats code neatly like this:
Messaging.SingleEmailMessage contactEmail = new Messaging.SingleEmailMessage();
contactEmail.setSaveAsActivity(false);
contactEmail.setTemplateId(template.Id);
But enough about formatting. It's a little tough from the snippets to see exactly what's happening and how you'd want to alter this exactly. For example, you mention that this is filtering by role, but I don't find any references to role in the code. Similarly, I see references to "template.Id", which implies that template is either a variable or a parameter - but I don't see where "template" is being defined, which makes expanding that logic difficult.

About the roles: it looks like you're getting the recipient ids in several places, but they're always contact ids:
for(Contact c : closedLoopContacts){ 
      closedLoopEmailRecipientsIds.add(c.Id);
      system.debug('closedLoopContact: ' + c.Name + ' ' + c.Email); 
} 

for(String email : emailToId.keySet()){
    closedLoopEmailRecipientsIds.add(emailToId.get(email));
}

...and then you're using it here:
// create Dealer Notification emails to Contacts
for(Id recipientId : closedLoopEmailRecipientsIds){
    Messaging.SingleEmailMessage contactEmail = new Messaging.SingleEmailMessage();
    contactEmail.setSaveAsActivity(false);
    contactEmail.setTemplateId(template.Id);
    contactEmail.setWhatId(cl.Id);
    contactEmail.setTargetObjectId(recipientId);
    if(bdmSender != null) contactEmail.setOrgWideEmailAddressId(bdmSender);
    emails.add(contactEmail);
}
So you can't just add role to one contact query, because you're looping through ids when it comes time to decide what template to send. One thing you could do would be something like this (to replace the block above):
for (Contact con:[SELECT Id, Role__c FROM Contact WHERE Id IN :closedLoopEmailRecipientsIds) {
  String templateId = template.Id;
  if (con.Role__c == 'whatever role') { // guessing at the role field name and making up a role name here...
    templateId = [Select Id FROM EmailTemplate WHERE Name = 'Support: Case Response' LIMIT 1].Id; // not error-proof
  }
  Messaging.SingleEmailMessage contactEmail = new Messaging.SingleEmailMessage();
  contactEmail.setSaveAsActivity(false);
  contactEmail.setTemplateId(templateId); // NOTE THE CHANGE TO USE THE VARIABLE THAT DEPENDS ON THE ROLE
  contactEmail.setWhatId(cl.Id);
  contactEmail.setTargetObjectId(recipientId);
  if(bdmSender != null) contactEmail.setOrgWideEmailAddressId(bdmSender);
  emails.add(contactEmail);
}
Note that the way I'm getting the other template id isn't necessarily the best way to scale the feature, and definitely needs hardening. It's just to show the logic. (Also, be sure to avoid putting a template id into your code, because those will vary across environments, so what works in a sandbox won't in production.)

Hopefully that helps some - again, with a little more detail into some of the open questions above, I might be able to give you more. Good luck!