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
VaderVader 

Iterating Through a List of Values for Mail Messages

I have a custom object that stores an association between multiple users and a task. (i.e. Users that want to be informed regarding any task updates)  The object has the User ID (lookup field) and the Task ID (Text Field)  I am trying to use a trigger to send an email "After Udpate" of a task to that list of users.

 

Three things concern me,

 

1) I need to be able to take the emails addresses of the users in the custom object and concatonate them together to place in the "toAddresses" line and send an email after the update of a Task they are associated with.  Currently with the code below, it returns the value (User:{Email=xxxxx@yyyyy.com, Id=005d0000001V9oSAAS}) for each individual instead of just the email address.  Everything else seems to work correctly.

 

2)  I need to be able to append the email address of the individual that created the task to the list and I haven't been able to do that effectively.

 

3)  I feel like my code is not clean and will cause issues with potential DML limits.  I can disable on any mass imports but I am worried about day to day usage bumping against govenor limits.

 

Thanks in advance for any help!

 

 

trigger SendEmailonTaskUpdate on Task (after update) { 
  
   	String taskId = ApexPages.currentPage().getParameters().get('Id');  
	
    List<Task_Informed_Users__c> emailList = New List<Task_Informed_Users__c>();
    emailList =  [Select Informed_User__c from Task_Informed_Users__c where Task_ID__c =: taskId];
    
	String taskCreatedByUser = [select Email from User where Id = :trigger.old[0].CreatedById].Email;
	
	String emailAddr = '';
	for (Integer i = 0; i < emailList.size(); i++) {
	
		If (emailAddr =='') {
				emailAddr = emailAddr + [Select Email from User Where Id=: emailList[i].Informed_User__c];
			} 
		Else 
			{
				emailAddr = emailAddr + '; ' + [Select Email from User Where Id=: emailList[i].Informed_User__c];
		}
	}
	
	If (emailAddr != 'null') {
		emailAddr = emailAddr + '; ' + taskCreatedByUser;
	} Else {
		emailAddr = taskCreatedByUser;
	}
	    
   	Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();     
        
    String[] toAddresses = new String[] {emailAddr};
    mail.setToAddresses(toAddresses);
    
    mail.setSubject('Details : ' + trigger.new[0].Subject + ' AND ' + trigger.new[0].Status);
    
    mail.setPlainTextBody('The details for Task: ' + trigger.new[0].Subject + ' have been changed.');
    mail.setHtmlBody('The details for Task: <b>' + trigger.new[0].Subject + '</b> have been changed </b>');   
   
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}

 

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
Avidev9Avidev9

I am pretty much positive about the fact that "URL cannor be read from trigger". Triggers are at db level and they dont have any connection with pages/URL

 

The query should be 

 

emailList = [Select Informed_User__c, Informed_User__r.Email, CreatedBy.Email from Task_Informed_Users__c where Task_ID__c IN: trigger.newMap.keySet()];

All Answers

VaderVader

Well I am not sure it's completely effecient in terms of coding practice but I was able to work out a solution that got rid of the SOQL in the For Loop and I was also able to concatonate all the users from the custom object with the CreatedBy user for the task.  If there are things I can do below to make this better, let me know.  As of now this code seems to be working just fine.

 

To fix what I had, I first changed the SOQL to capture both Informed_User__c and  Informed_User__r.Email... I then created a String named emailAddr.  I then looped through the results of the SOQL query and added the email value to that string with each pass of the loop.  (This removed the SOQL from the loop... much better for getting rid of excessive queries and potential DML limits.

 

Finally I added the result of the CreatedBy query to the emailAddr string by adding the following after the loop was completed:  emailAddr.Add(taskCreatedByUser);

 

Updated code below.

 

trigger SendEmailonTaskUpdate on Task (after update) {       
   	
   	//********************************************************************************
   	//	Capture the task ID from the URL for use in the emailList query
   	//********************************************************************************
   	
   	String taskId = ApexPages.currentPage().getParameters().get('Id'); 
		
	//********************************************************************************
	//  Create a list object with the informed users and append
	//		the created by user to the list for the "To" addresses
        //********************************************************************************
    List<Task_Informed_Users__c> emailList = New List<Task_Informed_Users__c>();
     emailList =  [Select Informed_User__c, Informed_User__r.Email from Task_Informed_Users__c where Task_ID__c =: taskId];
    
	String taskCreatedByUser = [select Email from User where Id = :trigger.old[0].CreatedById].Email;
	
	
	//********************************************************************************
	//	Iterate through list to create a "To" string that can be
	//		placed on one line
	//********************************************************************************
	String[] emailAddr = new String[]{};
	
	for (Integer i = 0; i < emailList.size(); i++) {
		//System.debug(emailList[i].Informed_User__c);		
		emailAddr.add(emailList[i].Informed_User__r.Email);
	}	
	
	emailAddr.Add(taskCreatedByUser);
	
    //********************************************************************************
    //	Begin constructing email message code
    //********************************************************************************
    
   	Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();     
     
    String[] toAddresses = emailAddr;
    mail.setToAddresses(toAddresses);
    
    mail.setSubject('Details : ' + trigger.new[0].Subject + ' AND ' + trigger.new[0].Status);
    
    mail.setPlainTextBody('The details for Task: ' + trigger.new[0].Subject + ' have been changed.  The Status of the task is ' + trigger.new[0].Status + '.  The Task description is ' + trigger.new[0].Description);
    //mail.setHtmlBody('The details for Task: <b>' + trigger.new[0].Subject + '</b> have been changed </b>');

    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

}

 

Avidev9Avidev9

I would suggest few changes

 

  • You cant access URL from a Trigger !!!!!!!!  This will never work 
    String taskId = ApexPages.currentPage().getParameters().get('Id'); 
  • Instead of using list I guess you should use Set to avoid dupes
  • I guess you can get the Createdby email in the same SOQL

Something like this(changes are in bold)

trigger SendEmailonTaskUpdate on Task(after update) {

    

    //********************************************************************************
    //  Create a list object with the informed users and append
    //		the created by user to the list for the "To" addresses
    //********************************************************************************
    List < Task_Informed_Users__c > emailList = New List < Task_Informed_Users__c > ();
    emailList = [Select Informed_User__c, Informed_User__r.Email, CreatedBy.Email from Task_Informed_Users__c where Task_ID__c = : trigger.newMap.keySet()];


    //********************************************************************************
    //	Iterate through list to create a "To" string that can be
    //		placed on one line
    //********************************************************************************
    Set < String > emailAddr = new Set < String > ();

    for (Integer i = 0; i < emailList.size(); i++) {
        //System.debug(emailList[i].Informed_User__c);		
        emailAddr.add(emailList[i].Informed_User__r.Email);
        emailAddr.add(emailList[i].CreatedBy.Email);
    }



    //********************************************************************************
    //	Begin constructing email message code
    //********************************************************************************

    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

    String[] toAddresses = emailAddr;
    mail.setToAddresses(toAddresses);

    mail.setSubject('Details : ' + trigger.new[0].Subject + ' AND ' + trigger.new[0].Status);

    mail.setPlainTextBody('The details for Task: ' + trigger.new[0].Subject + ' have been changed.  The Status of the task is ' + trigger.new[0].Status + '.  The Task description is ' + trigger.new[0].Description);
    //mail.setHtmlBody('The details for Task: <b>' + trigger.new[0].Subject + '</b> have been changed </b>');

    Messaging.sendEmail(new Messaging.SingleEmailMessage[] {
        mail
    });

}

 

VaderVader

Thanks for the reply!

 

I am actually not able to use the suggested query:  

emailList = [Select Informed_User__c, Informed_User__r.Email, CreatedBy.Email from Task_Informed_Users__c where Task_ID__c = : trigger.newMap.keySet()];

 

The created user is stored on the Task object while the "Informed Users" are stored in a custom object.  There can be a many to one relationship between the Infomred users and the task.

 

 

As far as the URL not being read from the trigger, there definitely may be something to that, however, I added the ID,stored in the varialbe taskId and assigned by  

String taskId = ApexPages.currentPage().getParameters().get('Id');

to the email message and ran a few tests.  I am able to populate the ID from this variable in the email messages and all emails go out that are supposed to based on the values in the Informed User object.

 

Not sure if Salesforce is allowing url's to be read in triggers now or if there is some sort of luckly glitch that is allowing me to execute the code correctly...

Avidev9Avidev9

I am pretty much positive about the fact that "URL cannor be read from trigger". Triggers are at db level and they dont have any connection with pages/URL

 

The query should be 

 

emailList = [Select Informed_User__c, Informed_User__r.Email, CreatedBy.Email from Task_Informed_Users__c where Task_ID__c IN: trigger.newMap.keySet()];
This was selected as the best answer
VaderVader

I updated my trigger with the query for the email list as you suggested and all is working well.  Marking your info as the solution.

 

Thanks!