+ Start a Discussion
Ben Wild 8Ben Wild 8 

Scheduled Batch Apex class to send email reminder: Not sending messages

I've written a sheduled batch apex class that I wasnt to run every day and send out an email to every user that has a custom Action object record that has passed its "Due Date". I have written the code below but the sendEmail method just throws an exception every time and despite catching it, the error doesnt really say anythinf useful. My code is below:
global class ActionOverdueNotification implements Database.Batchable<sObject>, Schedulable, Database.Stateful {

    //Variable Section
    global FINAL String strQuery;
    global List<String> errorMessages = new List<String>();
    global ActionOverdueNotification() { 
        this.strQuery = getBatchQuery();
    //Returns the Query String to Batch constructor to fetch right records.
    private String getBatchQuery() {
        String strQuery = 'SELECT Id, Due_Date__c, Owner_Email__c FROM Action__c WHERE Due_Date__c < TODAY'; 
        return strQuery;
    //Batch Start method
    global Database.QueryLocator start(Database.BatchableContext BC) {
        return Database.getQueryLocator(strQuery);

    //Batch Execute method calls findCostForWoD method
    global void execute(Database.BatchableContext BC, List<sObject> scopeList) {
        System.debug(LoggingLevel.INFO, '== scopeList size ==' + scopeList.size());
        List<Action__c> actList = (List<Action__c>) scopeList;
        if(!actList.isEmpty()) { 
            List<Messaging.SingleEmailMessage> mailList = new List<Messaging.SingleEmailMessage>();
            EmailTemplate et=[Select id from EmailTemplate where name = 'Action Template' limit 1];
            for (Action__c act : actList)
                Messaging.SingleEmailMessage message = new Messaging.SingleEmailMessage(); 
                String[] toAddresses = new String[] {act.Owner_Email__c};
                Message.setSenderDisplayName('System Admin');
                Message.SaveAsActivity = false;
            if(!mailList.isEmpty()) {
                catch (Exception ex) {
                    errorMessages.add('Unable to send email: '+ ex.getStackTraceString());

    //Batch Finish method for after execution of batch work
    global void finish(Database.BatchableContext BC) { 
        AsyncApexJob aaj = [Select Id, Status, NumberOfErrors, JobItemsProcessed, MethodName, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =:BC.getJobId()];
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {aaj.CreatedBy.Email};
        mail.setSubject('JOB Salesforce Send Notification Batch: ' + aaj.Status);
        String bodyText='Total Job Items ' + aaj.TotalJobItems + ' Number of records processed ' + aaj.JobItemsProcessed + ' with '+ aaj.NumberOfErrors + ' failures.\n';
        bodyText += 'Number of Error Messages ' + errorMessages.size() + '\n';
        bodyText += 'Error Message' + String.join(errorMessages, '\n');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    //Method which schedules the ProductDownloadBatch
    global void execute(SchedulableContext sc) {        
        ActionOverdueNotification snInstance = new ActionOverdueNotification();
        ID batchprocessid = Database.executeBatch(snInstance);

The error message is as follows:

Total Job Items 1 Number of records processed 1 with 0 failures.
Number of Error Messages 1
Error MessageUnable to send email: Class.ActionOverdueNotification.execute: line 45, column 1

Any ideas what I'm doing wrong?
Only User, Contact, Lead, or Person objects are allowed for targetObjectId. So at line no 35, you are setting custom object id.
Magulan Duraipandian
Ben Wild 8Ben Wild 8
Ah ok, in that case how do I pass the fields from the custom object to the email template?


Lakshan Weeraratne 12Lakshan Weeraratne 12
Also would like to know this^^^