0

I want to send email to user about his open tasks. Each user will have more than one task.

I have a set of taskIds and querying all tasks based on these IDs.

How do I get email address of task owners and send email with list of tasks for each owner.

//Task User Map Map<ID, List<Task>> tasksByUserMap = new Map<ID, List<Task>>(); // Query all tasks List<Task> lstReminderTasks = [SELECT ID, Subject, ActivityDate, WhatId, OwnerId, Owner.Email FROM Task WHERE ID IN: taskIds AND Status = 'Open' ]; 

Here's a sample data for the above query:

Sample Data

Owners XYZ and ABC have two tasks each.

//Build Task Owner Map from the list for(Task task: lstReminderTasks){ List<Task> userTasks = tasksByUser.get(taskRecord.OwnerId); if(userTasks == null) { tasksByUserMap.put(task.OwnerId, userTasks = new List<Task>()); } userTasks.add(task); } Messaging.SingleEmailMessage mail = = new Messaging.SingleEmailMessage(); OrgWideEmailAddress owe = [SELECT ID,DisplayName,Address FROM OrgWideEmailAddress WHERE DisplayName = 'Support']; // Build email content and To addresses if(!tasksByUserMap.isEmpty()) { String[] toaddress; htmlBody += 'Below tasks are due : ' + '</br> </br>'; htmlBody += '<table><tr><th>Task Subject</th><th>Due Date</th><th>Priority</th></tr>' for(Task t : lstReminderTasks ) { htmlBody += '<tr>'; htmlBody += '<td>'+ t.Subject +'</td>'; htmlBody += '<td>'+ t.ActivityDate +'</td>'; htmlBody += '<td>'+ t.Priority+'</td>'; htmlBody += '</tr>' mail.setOrgWideEmailAddressId(owe.ID); mail.setSaveAsActivity(false); mail.setToAddresses(toAddress); // How to get toAddress here ? mail.setHtmlBody(htmlBody ); } } 

I need help with -

  • Refining my code to get the ToAddress based on owner ID
  • Create a data structure / map to send email to owner regarding their tasks only.
5
  • are you OK with using VF email? Commented Apr 7, 2022 at 0:25
  • @cropredy This is in a scheduled batch job so emails are sent once in a month Commented Apr 7, 2022 at 1:37
  • Yes but can the email be a VF email template rather than hard-coded html? Commented Apr 7, 2022 at 1:40
  • We need the values dynamically based on the query in the batch job. My issue is not with the email template , its with creating a list of "To address" based on tasks owned by each ownerId. @cropredy Commented Apr 7, 2022 at 2:08
  • ignore my VF email comment - I forgot that there is no related list between User and Task - my answer tho addresses this Commented Apr 7, 2022 at 2:52

1 Answer 1

0

Given this is a batch job

public Database.QueryLoactor start(Database.BatchableContext bc) { return [SELECT Id, Email FROM User]; } public void execute(Database.BatchableContext bc User[] users) { // collect all userIds to find open Tasks Map<Id,User> usersById = new Map<Id,User> (users); // get all Open tasks for these userIds Map<Id,Task[] openTasksByUserId = new Map<Id,Task[]>(); for (Task t : [SELECT ... FROM Task WHERE OwnerId IN : usersById.keySet() AND Status = 'Open'] ) { if (!openTasksByUserId.containsKey(t.OwnerId)) { openTasksByUserId.put(t.OwnerId,new List<Task>(); } opentasksByUserId.get(t.OwnerId).add(t); }; // for all users with open Tasks, send email w/ tasks for (Id userId: openTasksByUserId.keySet()) { Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.toAddresses = new List<String> {usersById.get(userId).Email}; String[] displayableTasks = new List<String>(); for (Task t: openTasksByUserId.get(userId)) { displayableTasks.add(htmlMe(t)); } mail.setHtmlBody(displayableTasks); ... mail.send(); // there are limits to worry about, you can't send too many emails/day by apex } } private String htmlMe(Task t) { return someFormnatted HTML based on a Task } public void finish(Database.BatchableContext bc) {} 
4
  • Thanks @cropredy Do we need usersById ? I have the queried task owner email address in lstReminderTasks. But not sure how to build the map so that each email lists only task related to that user. Commented Apr 7, 2022 at 3:59
  • That is what my solution does. See openTasksByUserId. Commented Apr 7, 2022 at 4:09
  • Thank you @cropredy, just unsure why we need User[] users and usersById . I have updated my quesion with sample data which already has owner email address as well. Commented Apr 7, 2022 at 4:29
  • Sure, one could but the pattern above is so common that I reuse it over and over again. It arguably is a better separation of concerns pattern than exploiting the owner.email field on the first Task in each list. There is no performance penalty of note to build usersById. Commented Apr 7, 2022 at 4:54

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.