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
Shruti TandonShruti Tandon 

trigger to populate email id of contacts associated with an account on account page (insert,update,delete)


trigger AccEmail on Contact (after insert,after update) {
    String Em='';
    if(trigger.isInsert || trigger.isUpdate ){
    Set <String> accID = New Set <String> ();
    For (Contact con: Trigger.new) {
        if (con.AccountId != Null ) {
        accID.add (con.AccountId);
        }
    }
   
    if (accID.size ()> 0) {
        List <Account> upAccList = new List <Account> ();
       
      for(Account acc : [Select id, EmailId__c,
                             (Select Id, Email From Contacts)
                        From Account Where Id In : accID])
  
       for(Contact con : acc.contacts)
       {
        if(con.Email != null)
        {
            Em = Em + ', ' + con.Email;
        }
        acc.Contact_Names__c = names;
       
     upAccList.add(acc);
   }   
   update upAccList;
}
    }
Deepali KulshresthaDeepali Kulshrestha
Hi Shruti,

I am not able to properly find motive of using "Names" variable here, it would be very helpful if you elaborate things clearly.
But after going through the code, I assume you are trying to populate Contact_Names__c field with email field of Contact.
Please use Em instead of using Names.

trigger PopulateAcc on Contact (before insert,after update) {
    String Em='';
    if(trigger.isInsert || trigger.isUpdate ){
    Set <String> accID = New Set <String> ();
    For (Contact con: Trigger.new) {
        if (con.AccountId != Null ) {
        accID.add (con.AccountId);
        }
    }
   
    if (accID.size ()> 0) {
        List <Account> upAccList = new List <Account> ();
       
      for(Account acc : [Select id, EmailId__c,
                             (Select Id, Email From Contacts)
                        From Account Where Id In : accID])
  
       for(Contact con : acc.contacts)
       {
        if(con.Email != null)
        {
            Em = Em + ', ' + con.Email;
        }
        acc.Contact_Names__c = Em;//Names
       
     upAccList.add(acc);
   }   
   update upAccList;
}
    }
}


I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.
Thanks and Regards,
Deepali Kulshrestha
Abdul KhatriAbdul Khatri
HI Shruti,

I made few updates you missing like Delete, Initializing Em variable per Accounts etc. I have also included the test class with 100% coverage of Insert, Update and Delete.
 
trigger AccountEmailUpdateFromContact on Contact (after insert, after update, before delete) {

	List<Contact> contactList = (Trigger.isInsert || Trigger.isUpdate ? Trigger.new : Trigger.old);
    
    String Em='';
    Set <String> accID = New Set <String> ();
    For (Contact con: contactList) {
        if (con.AccountId != Null ) {
            accID.add (con.AccountId);
        }
    }
   
    if (accID.size ()> 0) {
        List <Account> upAccList = [Select id, Contact_Names__c,
                             (Select Id, Email From Contacts)
                        From Account Where Id In : accID];
       
        for(Account acc : upAccList)
        {
            Em = '';
            for(Contact con : acc.contacts)
            {
                if(con.Email != null)
                {
                    Em = Em + ', ' + con.Email;
                }
            } 
            acc.Contact_Names__c = Em;            
        }
        update upAccList;
    }
}

Test Class
@isTest
public class AccountEmailUpdateFromContact_Test {

    static testMethod void test_method(){

		Account acct = new Account (Name = 'Test Account');
        insert acct;
	
        List<Contact> contactList = new List<Contact> {
            		new Contact (LastName = 'Test 1', Email = 'test1@test.com', AccountId = acct.Id),
                    new Contact (LastName = 'Test 2', Email = 'test2@test.com', AccountId = acct.Id),
					new Contact (LastName = 'Test 3', Email = 'test3@test.com', AccountId = acct.Id)                
        };
        insert contactList;
        
        Account acctToVerify = [SELECT Contact_Names__c FROM Account WHERE Id = :acct.Id];
        system.assert(acctToVerify.Contact_Names__c.contains('test1@test.com, test2@test.com, test3@test.com'));
        
        Contact contactToDelete = [SELECT Id FROM Contact WHERE Email = 'test3@test.com' LIMIT 1];
        Delete contactToDelete;
        
        Account acctToVerify2 = [SELECT Contact_Names__c FROM Account WHERE Id = :acct.Id];
        system.assert(acctToVerify2.Contact_Names__c.contains('test1@test.com, test2@test.com'));        
        
        Contact contactToUpdate = [SELECT Id FROM Contact WHERE Email = 'test2@test.com' LIMIT 1];
        contactToUpdate.Email = 'test4@test.com';
        Update contactToUpdate;

        Account acctToVerify3 = [SELECT Contact_Names__c FROM Account WHERE Id = :acct.Id];
        system.assert(acctToVerify3.Contact_Names__c.contains('test1@test.com, test4@test.com'));         
        
    }
}

​​​​​​​
Shruti TandonShruti Tandon
thankyou so much for the help, just wanted to clear out, since i am new to salesforce coding, will this code help me populate a custom text field on Accounts page with associated contacts email id in comma seperated list?
Abdul KhatriAbdul Khatri
Right now it is populating Email from Contacts / Account in the custom text field "Contact_Names__c" on Account, what we understood from your code. I am not sure what is Email Id is about and how and what information you enter in that field?
Shruti TandonShruti Tandon
that is exactly what i am looking for, thanks! also could you guide me how would i use a map in this situation? how would it be a better option?
Abdul KhatriAbdul Khatri
Map not needed in this situation. It will be just a waste of variable usage. If you have something else I can help you with that.

When you say "that is exactly what I am looking ...", I guess you are approving my code. 

Please mark that a best answer

I can help you with something else if you can send it over different ticket.
Shruti TandonShruti Tandon
also, how about not doing a for loop within a for loop, what approach will then work?
Abdul KhatriAbdul Khatri
OK Here is how what I think you can have a different way.
 
trigger AccountEmailUpdateFromContact on Contact (after insert, after update, before delete) {

	List<Contact> contactList = (Trigger.isInsert || Trigger.isUpdate ? Trigger.new : Trigger.old);
    
    String Em=''; 
    Set <String> accID = New Set <String> ();
    For (Contact con: contactList) {
        if (con.AccountId != Null ) {
            accID.add (con.AccountId);
        }
    }
   
    if (accID.size() > 0) 
    {
        List<Account> upAccList = new List<Account>();
        
        List<Contact> contactList = [SELECT Id, Email, AccountId FROM Contact WHERE AccountId = :accID ORDER BY AccountId];
        
        Id idAccountCurr = null;
        Em = '';
        for(Contact con : contactList) {         
            
            if(con.Email != null)
            {
                Em = Em + ', ' + con.Email;
            }	

            if(idAccountCurr != null && idAccountCurr != con.AccountId){
                Account acc = new Account (Id = idAccountCurr);
                acc.Contact_Names__c = Em;
                upAccList.add(acc);
                
                Em = '';
            }            
            idAccountCurr = con.AccountId;
        }
        
        Account acc = new Account (Id = idAccountCurr);
        acc.Contact_Names__c = Em;
        upAccList.add(acc);        

        update upAccList;
        
    }
}

Can you mark the first one as best if it helped. Thanks
Shruti TandonShruti Tandon
this trigger and the previous trigger dont work when i delete an email id,the email id in the custom text field still persists.
Abdul KhatriAbdul Khatri
Can you give more insight about Eamil Id? That's the particular attribute that we have been asking what is exactly the purpose of that field as we haven't seen any usage of that field in your code.

Please provide the process how it is functioning?
Shruti TandonShruti Tandon
The EmailId__c is a custom text field on my account object, which is being used to display all the contact email id associated with an account. I was replacing it wherever you have used Contact_Names__c , and it sas working fine for me....except the fact the when I am deleting the contact from account related list, the emailId__c field is still showing the deleted contact's email in the list
Abdul KhatriAbdul Khatri
Can you make sure in the trigger definition you have before delete. I saw that was missing in the code you provided.
 
trigger AccEmail on Contact (after insert,after update) {

....

}

 
Shruti TandonShruti Tandon
Yes , it was not mentioned, but that was something I wanted a solution for, how would it work if I deleted a contact?
Abdul KhatriAbdul Khatri
Change this
trigger AccEmail on Contact (after insert,after update) {

To this
trigger AccEmail on Contact (after insert,after update, before delete) {

​​​​​​​
Shruti TandonShruti Tandon
hello abdul, my trigger is not reflecting change in update if i change the account the contact is associated with,how would that be solved?
Abdul KhatriAbdul Khatri
I don't see any issues in the code. Please provide some examples so that I can better understand what do you mean not working.

Also share the code you have so I can match that with mine?
Shruti TandonShruti Tandon
okay so what is happening is, i want the code to work on trigger.old as well, to ensure tht if a change the account lookup field on contact object(say if account A had contact named 'c', and now i want to associate Account B with 'c', the Account A is still showing 'c' 's email id in itscustom email id field, this should not happen . since nesting for loop is not a good practice, i wanted to use a map for adding values of email id on my account custom field. on deleting the contact, the trigger is not working and i have been asked to write the trigger once i delete the contact fr a particular account, so that email id in custom field fr tht account is deleted as well!
Abdul KhatriAbdul Khatri
OK Try this
trigger AccountEmailUpdateFromContact on Contact (after insert, after update, before delete) {

	List<Contact> contactList = (Trigger.isInsert || Trigger.isUpdate ? Trigger.new : Trigger.old);
    
    String Em=''; 
    Set <String> accID = New Set <String> ();
    For (Contact con: contactList) {
        if (con.AccountId != Null ) {
            accID.add (con.AccountId);
        }
        
        if(Trigger.IsUpdate && Trigger.oldMap.get(con.Id).AccountId != null && con.AccountId != Trigger.oldMap.get(con.Id).AccountId)
        {
            accID.add(Trigger.oldMap.get(con.Id).AccountId);
        }
    }
   
    if (accID.size() > 0) 
    {
        List<Account> upAccList = new List<Account>();
        
        List<Contact> contactList = [SELECT Id, Email, AccountId FROM Contact WHERE AccountId = :accID ORDER BY AccountId];
        
        Id idAccountCurr = null;
        Em = '';
        for(Contact con : contactList) {         
            
            if(con.Email != null)
            {
                Em = Em + ', ' + con.Email;
            }	

            if(idAccountCurr != null && idAccountCurr != con.AccountId){
                Account acc = new Account (Id = idAccountCurr);
                acc.Contact_Names__c = Em;
                upAccList.add(acc);
                
                Em = '';
            }            
            idAccountCurr = con.AccountId;
        }
        
        Account acc = new Account (Id = idAccountCurr);
        acc.Contact_Names__c = Em;
        upAccList.add(acc);        
        
        system.debug('upAccList : ' + upAccList);
        update upAccList;

    }
}

 
Shruti TandonShruti Tandon
this is deleting the email id on account page but deleting all the ids even for contacts still associated with it