You need to sign in to do that
Don't have an account?
Gleb Vrevsky
Best way to avoid SendEmail limits
We have a custom object - Employees. I have an Apex class to send an email to all employees. It is scheduled to be sent once a month, using "Schedule Apex". But it fails with an error: "Scheduler: failed to execute scheduled job: jobId: 707G000003Axx2S, class: common.apex.async.AsyncApexJobObject, reason: Too many Email Invocations: 11"
Obviously, it fails due to governor limits (more than 10 sendEmails). Please, find my Apex class below. What is the best way to make it work for more than 100 employees? Should I rework it as a Batch Apex or...?
Any example would be much appreciated.
Obviously, it fails due to governor limits (more than 10 sendEmails). Please, find my Apex class below. What is the best way to make it work for more than 100 employees? Should I rework it as a Batch Apex or...?
Any example would be much appreciated.
global class EmployeeMonthlyEmail implements Schedulable { global void execute(SchedulableContext ctx) { List<Employee__c> empList = [SELECT Id, Name, FirstName__c, LastName__c, Email__c, Birthdate__c, MobilePhone__c, PersonalEmail__c, Skype__c FROM Employee__c WHERE Status__c != 'Disabled' ]; for(Employee__c emp:empList){ sendEmailToEmployee(emp); } } public static Boolean sendEmailToEmployee(Employee__c emp){ Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.setToAddresses(new String[]{emp.Email__c}); mail.setReplyTo('inese@scandiweb.com'); mail.setSenderDisplayName('Scandiweb Salesforce'); mail.setSubject('Employee Info - ' + emp.Name); mail.setBccSender(false); mail.setUseSignature(false); mail.setCharset('UTF-8'); String emailText = '<p>Hello ' + emp.FirstName__c +',</p>'+ '<p>Please, check information we have, and let us know if we should update it.'+ '<br />You are welcome to email inese@scandiweb.com with new information'+ '<br />Thank you in advance ;)</p>'+ '<p>First Name: '+ emp.FirstName__c + '<br />'+ 'Last Name: '+ emp.LastName__c + '<br />'+ 'Birthdate: '+ emp.Birthdate__c + '<br />'+ 'Mobile Phone: '+ emp.MobilePhone__c + '<br />'+ 'Personal Email: '+ emp.PersonalEmail__c + '<br />'+ 'Skype: '+ emp.Skype__c + '</p>'; List<CourseEnrollment__c> courseList = [SELECT Course__r.Name, Status__c, DateExpectedOn__c, DateCompletedOn__c FROM CourseEnrollment__c WHERE Employee__c = :emp.Id ORDER BY Status__c DESC ]; emailText = emailText + mailTextEmployeeCourseList(courseList); emailText = emailText + '</p>'+ '<p>Please excuse us for any issues, we are still in process of getting better ;)</p>'; mail.setHtmlBody(emailText); try { List<Messaging.SendEmailResult> results = Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); if (!results.get(0).isSuccess()) { return false; } else { return true; } } catch (Exception e) { //System.debug('Exception has occurred: ' + e.getMessage()); return false; } } public static String mailTextEmployeeCourseList(List<CourseEnrollment__c> courseList) { String text = ''; text = text + '<p>Course List:'; if (courseList.size() >= 1) { for (CourseEnrollment__c ce : courseList) { text = text + '<br />' + ce.Course__r.Name + ' (' + ce.Status__c + ')'; if (ce.Status__c == 'Completed' && ce.DateCompletedOn__c != null) { text = text + ' - ' + ce.DateCompletedOn__c.day() + '/' + ce.DateCompletedOn__c.month() + '/' + ce.DateCompletedOn__c.year(); } else if (ce.Status__c == 'Expected' && ce.DateExpectedOn__c != null) { text = text + ' - ' + ce.DateExpectedOn__c.day() + '/' + ce.DateExpectedOn__c.month() + '/' + ce.DateExpectedOn__c.year(); } } } else { text = text + '<br />There are no Courses assigned to you ;('; } return text; } }
If fixed the issue with sendEmail limits, but the new issue is: Too many SOQL queries: 101. Do you have any thoughts what can be optimized in the code to fix it as well?
This SOQL query needs to be moved out of the FOR loop that starts on line #16. I would recommend making a MAP<Employee__c.Id, List<List<CourseEnrollment__c> before line #16 which would limit this code to 2 SOQL queries.
Here is the updated code below
@S.Karanraj, with the updated query we are getting such error -> http://www.screencast.com/t/3M90RJos0LYM, saying that CourseEnrollment__r is not a child of Employee, hence not possible to run a subquery. But actually, there is Master-Details relationship between Employee and Course Enrollment -> http://www.screencast.com/t/crP7No4f
View inside of Course Enrollment object -> http://www.screencast.com/t/ukvrx3slxVN
View inside of Employee object -> http://www.screencast.com/t/YXncFfhsmJP
Is there anything I am missing?