0

I'm getting the following error in batch apex even though I'm using only 1 soql command:

Messaging.SendEmailError[getMessage=System.LimitException: LLC_BI:Too many SOQL queries: 201;getStatusCode=LIMIT_EXCEEDED;getTargetObjectId=0054p000003AAhtAAG;

Is there any reason why this would be? Does the email command use soql?

public with sharing class EmailHandler {
public List<Messaging.SingleEmailMessage> mailList;

 public Integer sendEmail(List<application__c> applications) {
    mailList = new List<Messaging.SingleEmailMessage>();     
    EmailTemplate emailTemplate = [Select Id,Subject,Description,HtmlValue,DeveloperName,Body from EmailTemplate where DeveloperName = 'Email_Template'];
    Id u;
    try{
        User user = [SELECT Id, IsActive FROM User WHERE Email = 'noreply@email.com'];
        u = user.Id;
        if(Test.isRunningTest()){
            EmailException e = new EmailException();
            e.setMessage('Test System.EmailException: Query failed.');
            throw e;
        }
    }catch(Exception e){
        u = UserInfo.getUserId();
    }
    for (application__c record : applications){

        Date dateOfStatusChange = record.dateOfStatusChange;
        Integer numberOfDaysBetween = dateOfStatusChange.daysBetween(Date.today());

        if( numberOfDaysBetween == 2 && record.Primary_Contact_Email__c != null && record.Primary_Contact_Email__c != ''){
            List<String> toAddresses = new List<String>();
            toAddresses.add(record.Primary_Contact_Email__c);

            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            mail.setWhatId(record.Id);
            mail.setTargetObjectId(u);
            mail.setTreatTargetObjectAsRecipient(false);
            mail.setToAddresses(toAddresses);
            mail.setTemplateID(emailTemplate.Id); 
            mailList.add(mail);

        }                         
    }

    if(mailList != null && mailList.size() > 0){
        try{
            Messaging.SendEmailResult [] result = Messaging.sendEmail(mailList,false);
            for(Messaging.SendEmailResult er : result){
                if(!er.isSuccess() || Test.isRunningTest()){
                    string errors = '';
                    for(Messaging.SendEmailError error : er.getErrors()){
                        errors+=error+'\n';
                    }
                    ErrorLog.log('Email Error', errors, null);
                }
            }
        }catch(Exception e){
            ErrorLog.log('Email Error', e, null);
        }
        return mailList.size();
    }
    return 0;

}

}

1

If you're using a Visualforce Email Template, then the queries used therein would count against your limits. Try to optimize your template, or reduce the batch size of your batch. You'll need to test and see how many queries a single rendering of your template requires.

Also, some notes:


record.Primary_Contact_Email__c != ''

A field queried from the database will never be an empty string.


mailList != null 

You initialized this variable. It will never be null.


if( numberOfDaysBetween == 2 && record.Primary_Contact_Email__c != null) {

If you had queried the records properly, you wouldn't need this check at all.


You went for 100% code coverage, at the expense of actual testing. You have no way of knowing if your code actually works because you created fake errors intentionally. I would be wary of this technique. 90% coverage is more than enough, and you won't have to worry about things breaking while you're not paying attention.

| improve this answer | |
  • Thank you that is actually very helpful to know. I'm still practising my apex development. Just as a further question though do you know what part's of of a visualforce email template count as a query? Is the template itself 1 query for example and additional fields included more? (I am using a visualforce email template in this case) – JJ Sunga Apr 22 at 3:59
  • To add my visualforce template uses 2 images from the documents section in SF. Would that increase the count for limits as well? – JJ Sunga Apr 22 at 4:19
  • @JJSunga The template itself does not use any queries, but if you call components that do use queries, those would count. That's likely the cause for the SOQL limits being reached. – sfdcfox Apr 22 at 11:00
  • Oh okay. I'm just not sure what components that would count towards queries. Do you know if I change the scheduler for now from 200 to a smaller amount would I need to reschedule my apex after I change it? (its already scheduled) – JJ Sunga Apr 22 at 13:20
  • @JJSunga Yes, changing it to a smaller value could help. Try 50 or 100. And yes, if you have a scheduler, you'd need to reschedule it. – sfdcfox Apr 22 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.