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
VDubVDub 

SObjectException Error on Email Trigger

Hi,

 

I'm new to triggers and I've been working on this for a week.  It works when I send it only to the Creator Email but when I add the Owner Email I get an error I don't know what I'm doing wrong. Any help would be much appreciated.

 

 It compiles fine but when I make an edit to the task I get this error:

 

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger QualityTaskEmailAlert caused an unexpected exception, contact your administrator: QualityTaskEmailAlert: execution of AfterUpdate caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: User.Email: Trigger.QualityTaskEmailAlert: line 39, column 1

 

 

Here is my trigger code, the line that is red is line 39:

 

/** This trigger sends an email message to the CreatedBy User when ActivityType = 'Maintenance - Quality' */
trigger QualityTaskEmailAlert on Task (after update) {
static final String SUBJECT = 'Quality Task Updated';
static final String BODY = 'You are being sent this email because the Quality Task "{0}" has been modified.\n\nCreated By: {5}\nAssigned To: {4}\nStatus: {1}\n\nClick the link below to view the task: \n{3}\n\nThanks, SFDC';

// Determine the creator's email and info about InsertionOrder for each Task, since it isn't in Trigger.new
List<Id> creatorIds = new List<Id>();
List<Id> ownerIds = new List<Id>();
List<Id> taskIDs = new List<Id>();
for (Task task : Trigger.new) {
if (task.Type == 'Maintenance - Quality') {
creatorIds.add(task.CreatedById);
ownerIds.add(task.OwnerId);
taskIDs.add(task.WhatId);
}
}

// Populate hashmap of Task Id to CreatedBy User's email address
List<User> creators = [Select Id, Email from User Where Id in :creatorIds];
Map<Id,String> creatorIdsToEmails = new Map<Id,String>();
for (User creator : creators) {
creatorIdsToEmails.put(creator.Id,creator.Email);
}
List<User> namecreators = [Select Id, FirstName, LastName from User Where Id in :creatorIds];
Map<Id,String> creatorIdsToNames = new Map<Id,String>();
for (User creator : creators) {
creatorIdsToNames.put(creator.Id,creator.Email);
}
// Populate hashmap of Owner UserId to Owner Name
List<User> owners = [Select Id, FirstName, LastName From User Where Id in :ownerIds];
Map<Id,String> ownerIdsToNames = new Map<Id,String>();
for (User owner : owners) {
ownerIdsToNames.put(owner.Id,owner.FirstName + ' ' + owner.LastName);
}

List<User> emailowners = [Select Id, Email From User Where Id in :ownerIds];
Map<Id,String> ownerIdsToEmails = new Map<Id,String>();
for (User owner : owners) {
ownerIdsToEmails.put(owner.Id,owner.Email);
}
// Populate hashmap of InsertionOrder Id (task.WhatId) to InsertionOrder Name
List<Task> tasks = [Select Id, Subject From Task Where ID in :taskIDs];
Map<Id,String> taskIDsToNames = new Map<Id,String>();
for (Task task : tasks) {
taskIDsToNames.put(task.Id, task.Subject);
}
for (Task task : Trigger.new) {
if (task.Type == 'Maintenance - Quality') {
try {
// send email to creator
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {creatorIdsToEmails.get(task.CreatedById)});
mail.setCcAddresses(new String[] {ownerIdsToEmails.get(task.OwnerId)});
mail.setSubject(SUBJECT);

// build a link to the relevant task programatically
String url = System.URL.getSalesforceBaseUrl().toExternalForm() + '/' + task.Id;

mail.setPlainTextBody(String.format(BODY,new String[]{
task.Subject ,task.Status, task.Type, url, OwnerIdsToNames.get(task.OwnerId), CreatorIdsToNames.get(task.CreatedById)
}));


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

if (!result[0].isSuccess()) {
System.debug(LoggingLevel.ERROR, 'Failed to send email'+result[0].getErrors()[0].getMessage());
}

} catch (System.EmailException ex) {
System.debug(LoggingLevel.ERROR, 'Encountered EmailException');
}
}
}
}

 

Best Answer chosen by Admin (Salesforce Developers) 
VDubVDub

Hi Vinita,

 

Thanks for your response.  It pointed me in the right direction.  I was creating hashmaps for each string but I figured out that you just have to map each string separately within the same hashmap. It works perfectly now. 

 

Here's my final code:

 

/** This trigger sends an email message to the CreatedBy User when ActivityType = 'Maintenance - Quality' */
trigger QualityTaskEmailAlert on Task (after update) {
static final String SUBJECT = 'Quality Task Updated';
static final String BODY = 'You are being sent this email because the Quality Task "{0}" has been modified.\n\nCreated By: {5}\nAssigned To: {4}\nStatus: {1}\n\nClick the link below to view the task: \n{3}\n\nThanks, SFDC';

// Determine the creator's email and info about InsertionOrder for each Task, since it isn't in Trigger.new
List<Id> creatorIds = new List<Id>();
List<Id> ownerIds = new List<Id>();
List<Id> taskIDs = new List<Id>();
for (Task task : Trigger.new) {
if (task.Type == 'Maintenance - Quality') {
creatorIds.add(task.CreatedById);
ownerIds.add(task.OwnerId);
taskIDs.add(task.WhatId);
}
}

// Populate hashmap of Task Id to CreatedBy User's email address and Name
List<User> creators = [Select Id, Email, FirstName, LastName from User Where Id in :creatorIds];
Map<Id,String> creatorIdsToEmails = new Map<Id,String>();
Map<Id,String> creatorIdsToNames = new Map<Id,String>();
for (User creator : creators) {
creatorIdsToEmails.put(creator.Id,creator.Email);
creatorIdsToNames.put(creator.Id, creator.FirstName +' '+creator.LastName);
}
// Populate hashmap of Owner UserId to Owner's email address and Name
List<User> owners = [Select Id, Email, FirstName, LastName From User Where Id in :ownerIds];
Map<Id,String> ownerIdsToEmails = new Map<Id,String>();
Map<ID,String> ownerIdsToNames = new Map<Id,String>();
for (User owner : owners) {
ownerIdsToEmails.put(owner.Id,owner.email);
ownerIdsToNames.put(owner.Id,owner.FirstName +' '+owner.LastName);
}
// Populate hashmap of InsertionOrder Id (task.WhatId) to InsertionOrder Name
List<Task> tasks = [Select Id, Subject From Task Where ID in :taskIDs];
Map<Id,String> taskIDsToNames = new Map<Id,String>();
for (Task task : tasks) {
taskIDsToNames.put(task.Id, task.Subject);
}
for (Task task : Trigger.new) {
if (task.Type == 'Maintenance - Quality') {
try {
// send email to creator
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {creatorIdsToEmails.get(task.CreatedById)});
mail.setCcAddresses(new String[] {ownerIdsToEmails.get(task.OwnerId)});
mail.setSubject(SUBJECT);

// build a link to the relevant task programatically
String url = System.URL.getSalesforceBaseUrl().toExternalForm() + '/' + task.Id;

mail.setPlainTextBody(String.format(BODY,new String[]{
task.Subject ,task.Status, task.Type, url, OwnerIdsToNames.get(task.OwnerId), CreatorIdsToNames.get(task.CreatedById)
}));


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

if (!result[0].isSuccess()) {
System.debug(LoggingLevel.ERROR, 'Failed to send email'+result[0].getErrors()[0].getMessage());
}

} catch (System.EmailException ex) {
System.debug(LoggingLevel.ERROR, 'Encountered EmailException');
}
}
}
}

All Answers

Vinita_SFDCVinita_SFDC

Hello,

 

This error occurs if you are using a field for which you did not query.

 

In List<User> owners = [Select Id, FirstName, LastName From User Where Id in :ownerIds]; you did not query for Email but you are using it in:

 

ownerIdsToEmails.put(owner.Id,owner.Email);

 

Query for Email as well and this should fix the error.

 

VDubVDub

Hi Vinita,

 

Thanks for your response.  It pointed me in the right direction.  I was creating hashmaps for each string but I figured out that you just have to map each string separately within the same hashmap. It works perfectly now. 

 

Here's my final code:

 

/** This trigger sends an email message to the CreatedBy User when ActivityType = 'Maintenance - Quality' */
trigger QualityTaskEmailAlert on Task (after update) {
static final String SUBJECT = 'Quality Task Updated';
static final String BODY = 'You are being sent this email because the Quality Task "{0}" has been modified.\n\nCreated By: {5}\nAssigned To: {4}\nStatus: {1}\n\nClick the link below to view the task: \n{3}\n\nThanks, SFDC';

// Determine the creator's email and info about InsertionOrder for each Task, since it isn't in Trigger.new
List<Id> creatorIds = new List<Id>();
List<Id> ownerIds = new List<Id>();
List<Id> taskIDs = new List<Id>();
for (Task task : Trigger.new) {
if (task.Type == 'Maintenance - Quality') {
creatorIds.add(task.CreatedById);
ownerIds.add(task.OwnerId);
taskIDs.add(task.WhatId);
}
}

// Populate hashmap of Task Id to CreatedBy User's email address and Name
List<User> creators = [Select Id, Email, FirstName, LastName from User Where Id in :creatorIds];
Map<Id,String> creatorIdsToEmails = new Map<Id,String>();
Map<Id,String> creatorIdsToNames = new Map<Id,String>();
for (User creator : creators) {
creatorIdsToEmails.put(creator.Id,creator.Email);
creatorIdsToNames.put(creator.Id, creator.FirstName +' '+creator.LastName);
}
// Populate hashmap of Owner UserId to Owner's email address and Name
List<User> owners = [Select Id, Email, FirstName, LastName From User Where Id in :ownerIds];
Map<Id,String> ownerIdsToEmails = new Map<Id,String>();
Map<ID,String> ownerIdsToNames = new Map<Id,String>();
for (User owner : owners) {
ownerIdsToEmails.put(owner.Id,owner.email);
ownerIdsToNames.put(owner.Id,owner.FirstName +' '+owner.LastName);
}
// Populate hashmap of InsertionOrder Id (task.WhatId) to InsertionOrder Name
List<Task> tasks = [Select Id, Subject From Task Where ID in :taskIDs];
Map<Id,String> taskIDsToNames = new Map<Id,String>();
for (Task task : tasks) {
taskIDsToNames.put(task.Id, task.Subject);
}
for (Task task : Trigger.new) {
if (task.Type == 'Maintenance - Quality') {
try {
// send email to creator
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {creatorIdsToEmails.get(task.CreatedById)});
mail.setCcAddresses(new String[] {ownerIdsToEmails.get(task.OwnerId)});
mail.setSubject(SUBJECT);

// build a link to the relevant task programatically
String url = System.URL.getSalesforceBaseUrl().toExternalForm() + '/' + task.Id;

mail.setPlainTextBody(String.format(BODY,new String[]{
task.Subject ,task.Status, task.Type, url, OwnerIdsToNames.get(task.OwnerId), CreatorIdsToNames.get(task.CreatedById)
}));


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

if (!result[0].isSuccess()) {
System.debug(LoggingLevel.ERROR, 'Failed to send email'+result[0].getErrors()[0].getMessage());
}

} catch (System.EmailException ex) {
System.debug(LoggingLevel.ERROR, 'Encountered EmailException');
}
}
}
}

This was selected as the best answer