0

Trying to send email from apex and receiving error:

System.EmailException: SendEmail failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Email body is required.: []

I have the line:

mail.setPlainTextBody(messageToSend);

Why does it not recognize that I have assigned a value for the body?

String messageToSend;
            List<String> ListOfMessages = new List<String>();
            Set<Id> AcctIds = new Set<Id>();
            String clientEmail;

List<AggregateResult> AggregateResultList = [SELECT AccountId, Account.Name name, COUNT(Id) co
                                             FROM Case
                                             WHERE CreatedDate = LAST_N_DAYS:1
                                             GROUP BY AccountId, Account.Name
                                             HAVING COUNT(Id)  = 2];


    for(AggregateResult aggr: AggregateResultList){
        String messageToSend = 'Account name: ' + aggr.get('name') + ' has ' + (Integer)aggr.get('co') + ' cases opened in the last 8 days.';
        ListOfMessages.add(messageToSend);

        Id accId = (Id)aggr.get('AccountId');
        AcctIds.add(accId);
    }
List<Case> caseList = [SELECT Id, AccountId, Account.Name,Parent_Project_if_applicable__r.Implementation_status__c,
                       Parent_Project_if_applicable__r.PM_Implementation_Status__c, 
                       Parent_Project_if_applicable__r.RCM_Implementation_Status__c,
                       Parent_Project_if_applicable__r.Client_Advisor_Email__c
                       FROM Case
                       WHERE AccountId IN :AcctIds];
  List<String> emailAdds = getAddresses();

for(Case cl:caseList){
    if(cl.Parent_Project_if_applicable__r.Implementation_status__c == 'Live - Closed Project'){
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(emailAdds);
        mail.setSenderDisplayName('Salesforce Support'); 
        mail.Subject = 'Subject Test Message';
        mail.setPlainTextBody(messageToSend);

        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
  • This code seems like it should have failed to compile, because of your attempt to name a duplicate variable inside your for loop. Did you copy it over here verbatim? FYI, it is recommended that you remove all debug statements and comments from your code before posting here. – Adrian Larson Nov 4 '19 at 18:39
0

The variable which you are using messageToSend is a method level variable. The first for loop also consists of the variable with same name. It is a good practice to name variables with different names. As the variables value is set in for loop level scope and not method level scope, its value is null. Therefore you are getting the error.

From your code what I understood is, you want to send email based on some conditions.

I would like to suggest you a solution.

  • In the first for loop create a map, Map<Id,String> accountIdEmailmessageMap

  • accountIdEmailmessageMap will have data of acount Id and the messageToSend for the account.

  • See code:

    Map<Id,String> accountIdEmailmessageMap = new Map<Id,String>(); for (AggregateResult aggr: AggregateResultList) { String messageToSend = 'Account name: ' + aggr.get('name') + ' has ' + (Integer)aggr.get('co') + ' cases opened in the last 8 days.'; Id accId = (Id)aggr.get('AccountId'); accountIdEmailmessageMap.put(accId,messageToSend); AcctIds.add(accId); }

  • Now in second for loop, when the if condition is true, get the value of messageToSend from map with account as key as shown below

String messageBody = accountIdEmailmessageMap.get(cl.AccountId);

  • And then set the mail's plain text body as mail.setPlainTextBody(messageBody);

Please let me know if you need any help.Thanks

1

Because it's null.

The variable is declared here:

String messageToSend;

At declaration time, it's initialized to null.

It's then shadowed in a for loop:

for(AggregateResult aggr: AggregateResultList){
    String messageToSend = 'Account name: ' + aggr.get('name') + ' has ' + (Integer)aggr.get('co') + ' cases opened in the last 8 days.';
    ListOfMessages.add(messageToSend);

The shadowing identifier goes out of scope at the end of the for loop, so we're still at null from the original declaration. Even if it didn't go out of scope, the value left would just be that of the last AggregateResult iterated over.

You then don't touch the variable again until you call

    mail.setPlainTextBody(messageToSend);

So it's null. As I suggested in a comment on one of your previous questions, you're using the wrong data structure here. You probably need a Map to correlate the messages you're generating to their related Cases or Accounts.

  • Shouldn't that cause a compile fail though? – Adrian Larson Nov 4 '19 at 18:39
  • @AdrianLarson Where? At the shadowing declaration? – David Reed Nov 4 '19 at 18:41
  • Yeah, attempt to declare a duplicate variable or something similar. – Adrian Larson Nov 4 '19 at 18:56
  • Shadowing's actually legal (if rarely useful or wise). It just has to be inside a new scope; otherwise you do get a duplicate variable error. – David Reed Nov 4 '19 at 18:57

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.