0

I am writing a batch class to send the emails based on certian criteria. I see that the parameters are passed right, no errors, but I end up receiving multiple duplicate emails when I run it. Here is the code

Two issues that I am trying to resolve

  1. When there are less than 10 emails to be sent out, the code works fine, but sends duplicate emails

  2. When there are more than more than 10 emails in the list that I am sending to, I get an error saying:

    FATAL_ERROR|System.LimitException: Too many Email Invocations: 11

Batch:

global void execute(Database.BatchableContext BC, List<OrderApi__Badge__c> scope){
    for(Order_c fbdge : [select Id,Description__c,Type__c,Contact__c,Contact__r.Date__c,Contact__r.FirstName,Contact__r.Email,Active__c,Type__r.Name From Order__c where (Type__r.Name ='A' or Type__r.Name ='B') and OrderApi__Is_Active__c =true and (Contact__r.Cat__c <> ' Life')]){
        bge.add(fbdge);
        contact.put(fbdge.Contact__c, fbdge.Contact__r.Email);
    }
    
    if(contact.size()>0){
        
        List<Messaging.SingleEmailMessage> mails = newList<Messaging.SingleEmailMessage>();
        List<String> email = new List<String>();
        List<String> ccemail = new List<String>();
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();  
        
        for(Id ids : contact.keyset()){
            
            email.clear();
            for(Order__c bdg :[select id,Contact__r.Email from Order__c where Contact__r.Email=:contact.get(ids) LIMIT 1]){
                
                email.add(bdg.Contact__r.Email);
            }
            Contact c = [select id, Email from Contact where email <> null limit 1];
            
            EmailTemplate templateId = [Select id from EmailTemplate where name = 'Test'];
            mail.setToAddresses(email);
            mail.setccAddresses(ccemail);
            mail.setTargetObjectId(c.Id);                                           mail.setTreatTargetObjectAsRecipient(false);
            mail.setTemplateID(templateId.Id);
            mail.setSaveAsActivity(false);
            mails.add(mail);
            
            if(mails.size())>0{                       
                
                Messaging.sendEmail(mails);
            }       
            
        }        
    }
}
global void finish(Database.BatchableContext BC){
    
}

}

1 Answer 1

2

Never call Messaging.sendEmail (nor any other method which consumes governors) inside a loop. Here's your basic problem:

for(Id ids : contact.keyset()){
    // some logic
    Messaging.sendEmail(mails);
    // don't ever do this
}

Instead, send the emails after your loop:

for(Id ids : contact.keyset()){
    // some logic
}
Messaging.sendEmail(mails);
// now you just invoke the send method once

Making this change will also fix the duplicates issue, as you are currently building one collection containing all the emails you want to send (good), then sending the entire collection for each element therein (bad).


Your other problem is you're sharing the same instance throughout the loop.

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
for(Id ids : contact.keyset()){
    mail.setToAddress(...);
    // each loop iteration overwrites the previous instance variables
}

Instead, declare your instance inside the loop.

for(Id ids : contact.keyset()){
    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    mail.setToAddress(...);
    // each loop iteration has its own instance
}
4
  • I did try that, but when I do that the same email is being sent to the same recipient multiple times. Not sure what I am missing here
    – user43146
    Commented Feb 16, 2018 at 23:21
  • @user43146 Adrian has pointed out first sight issue. your code is not following best practices (query inside loop etc) so your code will fail one or in another scenario. You should first read and follow best practice. Update your question after fixing basic issues, because if we write this in right manner it's like we are doing your job.
    – Himanshu
    Commented Feb 16, 2018 at 23:26
  • Got it. I think the instance inside for loop is what I have missed. Thank you Adrian. It worked now. Can we use batches for more than 200 emails. I have seen the documentations that we could use upto 1000, but just wanted to make sure if any of you might have used it?
    – user43146
    Commented Feb 17, 2018 at 2:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .