0

This question already has an answer here:

I have an Apex class that contains @future annotation method to send email. A Visualforce page is rendered as pdf and is sent as an email. I'm getting an exception in test class-

System.EmailException: SendEmail failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, No body supplied for the file attachment.: [fileAttachments]

Controller code(@future annotated)-

    PageReference pdf =  Page.ReceiptPrintPage;                       
        pdf.getParameters().put('AccId',parameter1); 
        pdf.getParameters().put('year',String.valueOf(parameter2));
        pdf.setRedirect(true);
        // Take the PDF content            
        Blob b;
      try{
            b = pdf.getContentAsPDF();
        }catch(Exception ex){
          System.debug('ex'+ex);
      }    

        // Create the email attachment
        String filename = parameter3 + '_receipt_' + parameter2 + '.pdf'; 
      Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
        //Messaging.EmailFileAttachment.setContentType(param1)                
        efa.setFileName(filename);
        efa.setBody(b);                               

        // Sets the paramaters of the email
        String subject = 'Recurring Donations Receipt for the Fiscal Year - ' + parameter2;                                                   
        body = 'Hello';
        email.setSubject(subject);
        email.setToAddresses(new String[] {parameter4});
        email.setPlainTextBody(body);           
      email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});                                             
        // Sends the email
        Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});

Test code-

    PageReference pdf =  Page.ReceiptPrintPage;
    pdf.getParameters().put('AccId',a1.Id); 
    pdf.getParameters().put('year',String.valueOf(fiscalYear));
    pdf.setRedirect(true);                
    Blob b;
    try{
        System.debug('before test content');      
        //b = pdf.getContentAsPDF();
        b = pdf.getContent();
    }catch(Exception ex){
        System.debug('ex'+ex);
    }  

    Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
    String filename = 'Receipt_' + fiscalYear + '.pdf';                                  
    efa.setFileName(filename);
    efa.setBody(b);                                   

    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    String body = 'Testing Email';
    String subject = 'Recurring Donations Receipt for the Fiscal Year - ' + fiscalYear; 

    email.setSubject(subject);
    email.setToAddresses(new String[] {'company@domain.com'});                
    email.setPlainTextBody(body);           
    email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});                                           
    Messaging.SendEmailResult[] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});              

How can I set body for file attachment?

marked as duplicate by Adrian Larson Oct 30 '17 at 7:37

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Please phrase your questions as questions. That is to say, your question will be better formed (more on topic according to the help center) if you ask something rather than suggest to others that they help you. – Adrian Larson Oct 27 '17 at 13:19
  • I'm sorry for the confusion. Thanks for the edit. – SFDC Developer Oct 27 '17 at 13:26
1

Your code is correct.
The issue you are having is that pdf.getContent(); is throwing an exception and the Blob variable b is null by the time efa.setBody(b); is executed (because it was never initialised).

Edit with what I mean, including the suggestion of @Rahul Sharma/Bob ;)

If you put the logic outside, its easier to cover with a test, and then you just leave the send-message out. something like...

private /*or public*/ static Messaging.SingleEmailMessage getEmailMessage(String paramAccountId, String paramYear, String paramFilePrefix, String paramToAddress);
    PageReference pdf =  Page.ReceiptPrintPage;
    pdf.getParameters().put('AccId',paramAccountId);
    pdf.getParameters().put('year',paramYear);
    pdf.setRedirect(true);
    // Take the PDF content
    Blob b;
    try {
        if (Test.IsRunningTest()) {
            b = Blob.valueOf('My awesome pdf, but txt');
        } else {
            b = pdf.getContentAsPDF();
        }
    } catch(Exception ex){
        System.debug('ex'+ex);
        // actually do something about it, like sending an error message to an admin or opening a ticket or something
    }


    // Create the email attachment
    String filename = paramFilePrefix + '_receipt_' + paramYear + '.pdf';
    Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
    //Messaging.EmailFileAttachment.setContentType(param1)
    efa.setFileName(filename);
    efa.setBody(b);

    // Sets the paramaters of the email
    String subject = 'Recurring Donations Receipt for the Fiscal Year - ' + paramYear;
    body = 'Hello';
    email.setSubject(subject);
    email.setToAddresses(new String[] {paramToAddress});
    email.setPlainTextBody(body);
    email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

    return email;
}

Having in the @future method something like

Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {getEmailMessage(parameter1, String.valueOf(parameter2), parameter3, paramater4)});

and in the test method something like

Messaging.SingleEmailMessage toBeTested = getEmailMessage(parameter1, String.valueOf(parameter2), parameter3, paramater4);

System.assertEquals(new List<String>{parameter4}, toBeTested.getToAddresses());
System.assertNotEquals(null, toBeTested.getFileAttachments());
System.assertEquals('Recurring Donations Receipt for the Fiscal Year - ' + String.valueOf(parameter2), toBeTested.getSubject());
....
  • So how to initialize? Yes you are right that pdf.getContent(); is throwing exception. What is the workaround for that? – SFDC Developer Oct 27 '17 at 12:58
  • The code you pasted is part of your test method or part of your @future method? – Sergio Alcocer Oct 27 '17 at 13:06
  • It is part of test method. I'll edit the question and put @future method. Please check the update in a while. – SFDC Developer Oct 27 '17 at 13:09
  • in the test code you could replace b = pdf.getContent(); by b = Blob.valueOf('Testing 1 2 3'). But if you really want to make a test, you should do a method that returns the email, and then in the test, make sure that the content of the email is what you expect and so on. Then in the method, use what @Rahul Sharma says, to generate the blob of 'Testing 1 2 3' only for test context, and then you could check for that in your asserts – Sergio Alcocer Oct 27 '17 at 13:47
  • Sorry, but I didn't understand that. "do a method that returns the email", means? In controller class you mean? Please elaborate in form of answer if possible. – SFDC Developer Oct 27 '17 at 18:38
0

Thanks a lot for providing solutions. I finally found the perfect solution to my stated problem. As suggested by Mohith Shrivastava here.

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