function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
sfdcFanBoysfdcFanBoy 

Email with PDF attachment - Error Opening the PDF

Hi All,

 

I need to send an email with a PDF attachment.  I have developed a normal visualforce page (didn't render as PDF). And then using apex code, am getting the body of it, and sending it as PDF attachment.

 

I am receving the email with the PDF attachment, but when I try to open the PDF, it isn't opening.  It gives the following decode error - "Adobe reader cannot open the PDF because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded)"

 

Below is the Apex class that is taking the body of vf page and making it a PDF attachment.  Please let me know if I am missing anything.  Thanks.

 

global class CustomersPDF_SendEmail implements Schedulable {

    global void execute(SchedulableContext sc) {    
        
        PageReference pdf = Page.CustomersPDF;
        pdf.getParameters().put('id','001O000000ECvg4');
     
        Blob body;
     
        try {
          body = pdf.getContent();
        } 
        catch (VisualforceException e) {
          body = Blob.valueOf('Some Text');
        }
     
        Messaging.EmailFileAttachment attach = new Messaging.EmailFileAttachment();
        attach.setContentType('application/pdf');
        attach.setFileName('KeyCustomers.pdf');
        attach.setInline(false);
        attach.Body = body;
     
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setUseSignature(false);
        mail.setToAddresses(new String[] {'abc@gmail.com'});
        mail.setSubject('Customers PDF - Demo');
        mail.setHtmlBody('Check the attachment!');
        mail.setFileAttachments(new Messaging.EmailFileAttachment[] { attach }); 
     
        // Send the email
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });               
    
    }
}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
liron169liron169

Easy. Inside the email template write:

 

<messaging:attachment renderAs="PDF" filename="myPDFFile.pdf">

<html>   
    <body>
        <!-- Here should have all the data that should be in the PDF.....

can be component that generate all the data   -->
    </body>
</html>
   </messaging:attachment>

All Answers

sfdcFanBoysfdcFanBoy
When I tried the below line

body = pdf.getContentaspdf();

I am not getting the error when I open BUT the PDF attachment is just plain blank! No information in it.

I tried with both VF page renderedas="PDF" and without it also. Same result both times.

Any thoughts?
mbhardwajmbhardwaj
Can you paste the code for Page.CustomersPDF as well here..
sfdcFanBoysfdcFanBoy

Here's the VF Code.  It has just 2 dataTables

 

<apex:page standardController="Key_Accounts_Snapshot__c" extensions="KeyAccountPDF" title="Key Accounts Report" showheader="false" sidebar="false" >

<head>
  <style type="text/css">

    @page{
        size: landscape;
    }    
    body {
        font-family:Arial Unicode MS;
        font-size:6pt;                               
    }    
    .c1{
        width:3.5%;
        font-weight:bold;
        text-align:center;
        float:center;   
    }
    .r1{
        height:20px;
    } 
    .bold { 
        font-weight:bold;
        text-align:center; 
    }
    .h1{
        width:33%;
    }      
  </style> 

</head>

<div>
<apex:panelGrid columns="3" width="100%" columnClasses="h1,h1,h1">
     <apex:outputText style="font-weight:bold;font-size:8pt; float:left;" value="Month: {!Month}"/>
     <apex:outputText style="font-weight:bold;font-size:9pt; text-align:center;" value="KEY ACCOUNTS MONTHLY REPORT"/>
     <apex:outputText style="font-weight:bold;font-size:8pt; float:right;" value="Generated On: {!GeneratedDate}"/>
</apex:panelGrid>
<br/>
<apex:dataTable columns="22" value="{!KeyAccountsSnapshot}" var="a" border="1" width="100%" rowClasses="r1"  >
    
    <apex:column value="{!a.Customer_Name__c}" style="width:20%;" headerClass="bold" >
        <apex:facet name="header"><b>Customers</b></apex:facet></apex:column>
    
    <apex:column value="{!a.Segment_Formula__c}" styleClass="c1" headerClass="bold">
         <apex:facet name="header"><b>Segment</b></apex:facet></apex:column>
    
    <apex:column value="{!a.Superbrand_formula__c}" styleClass="c1" headerClass="bold">
         <apex:facet name="header"><b>Superbrand</b></apex:facet></apex:column>

    <!--There are more similar columns, I removed them for simplifying it-->

</apex:dataTable>
</div>

<div style="page-break-before:always;">

<apex:panelGrid columns="3" width="100%" columnClasses="h1,h1,h1">
     <apex:outputText style="font-weight:bold;font-size:8pt; float:left;" value="YTD: {!Month}"/>
     <apex:outputText style="font-weight:bold;font-size:9pt; text-align:center;" value="KEY ACCOUNTS MONTHLY REPORT"/>
     <apex:outputText style="font-weight:bold;font-size:8pt; float:right;" value="Generated On: {!GeneratedDate}"/>
</apex:panelGrid>
<br/>
<apex:dataTable columns="22" value="{!KeyAccountsSnapshotYearly}" var="a" border="1" width="100%" rowClasses="r1"  >

    <apex:column value="{!a.CustName}" style="width:20%;" headerClass="bold" >
        <apex:facet name="header"><b>Customers</b></apex:facet></apex:column>
    
   <apex:column value="{!a.segment}" styleClass="c1" headerClass="bold">
        <apex:facet name="header"><b>Segment</b></apex:facet></apex:column>
    
   <apex:column value="{!a.superBrand}" styleClass="c1" headerClass="bold">
        <apex:facet name="header"><b>Superbrand</b></apex:facet></apex:column>
    
</apex:dataTable>
</div>

</apex:page>

 

Also, let you know, when I render this as PDF and check, it is working fine. 

 

Only when I send this VF via email as PDF attachment using the apex code that I pasted earlier, it is opening as BLANK PDF.

 

sfdcFanBoysfdcFanBoy

Ok Now this is not great.

 

I commented everything in the VF. And added this - <b>Hello World</b>

 

Even then it is the same error.  So this issue is not related to VF?

 

1) The adobe error message.  

 

When I used    body = pdf.getContent();

 

http://i41.tinypic.com/2q0oebp.jpg

 

 

2) The blank page.

 

When I used    body = pdf.getContentasPDF();

 

http://i43.tinypic.com/246qcfo.jpg

 

 

mbhardwajmbhardwaj
Can you paste the extension code as well?
The page looks fine to me..
sfdcFanBoysfdcFanBoy

Ok Thanks.

 

Here's the apex class

 

public with sharing class KeyAccountPDF{

        public Account a;
        public Key_Accounts_Snapshot__c d;


        public String custName {get; set;}
        public String mgmtEngmt {get; set;}

        public String segment{get;set;}
        public String superBrand{get;set;}
        public String sales{get;set;}
        public String csd{get;set;}
        public String difotCust{get;set;}
        public String difotNs{get;set;}
        public String custComplains{get;set;}
        public String returnLoads{get;set;}
        public String urgentOrders{get;set;}
        public String noProj{get;set;}
        public String newProj{get;set;}
        public String contVolum{get;set;}
        public String delivVolum{get;set;}
        public String twelvem{get;set;}
        public String cab{get;set;}
        public String wm{get;set;}
        public String bpc{get;set;}
        public String pcg{get;set;}
        public String ds{get;set;}
        public String ar{get;set;}

        
        public KeyAccountPDF(string a1,string a2, string a3, string a4, string a5, string a6, string a7, string a8,string a9, string a10, string a11,
string a12, string a13, string a14, string a15, string a16, string a17, string a18, string a19, string a20, string a21, string a22){
            this.custName=a1;
                         
             if(a2=='1') this.segment='CEIN';
             else if(a2=='2') this.segment='INCO';
             else if(a2=='3') this.segment='MISC';
             else if(a2=='4') this.segment='NSLR';
             else if(a2=='5') this.segment='OTCR';
             else if(a2=='6') this.segment='PCIN';
             else if(a2=='7') this.segment='RESC';
             else if(a2=='8') this.segment='DIST';
             else if(a2=='9') this.segment='KACC';                                       
             
             if(a3=='1') this.superBrand='YES';
             else if(a3=='0') this.superBrand='NO';
             
             this.mgmtEngmt=a4;
             this.sales=a5;
             this.csd=a6;
             this.difotCust=a7;
             this.difotNs=a8;
             this.custComplains=a9;
             this.returnLoads=a10;
             this.urgentOrders=a11;
             this.noProj=a12;
             this.newProj=a13;
             this.contVolum=a14;
             this.delivVolum=a15;
             this.twelvem=a16;
             this.cab=a17;
             this.wm=a18;
             this.bpc=a19;
             this.pcg=a20;
             this.ds=a21;
             this.ar=a22;
                 }
            
    Apexpages.StandardController controller;    
    public KeyAccountPDF(ApexPages.StandardController c) {        
        controller = c;        
        this.d = (Key_Accounts_Snapshot__c)controller.getRecord();
    }
    
    public String getMonth(){
        String strDate = String.valueOf(System.today());            
        String[] strDateList = strDate.split('-',3);        
        String sYear = strDateList[0];
        Integer intMonth = integer.valueOf(strDateList[1])-1;
        
        String iMonth = String.valueOf(intMonth);
        String sMonth;        
        
        if(iMonth=='0'){sMonth = 'Decemeber'; sYear = String.valueOf(integer.valueOf(sYear)-1);}
        else if(iMonth=='1') sMonth = 'January';
        else if(iMonth=='2') sMonth = 'February';
        else if(iMonth=='3') sMonth = 'March';
        else if(iMonth=='4') sMonth = 'April';
        else if(iMonth=='5') sMonth = 'May';
        else if(iMonth=='6') sMonth = 'June';
        else if(iMonth=='7') sMonth = 'July';
        else if(iMonth=='8') sMonth = 'August';
        else if(iMonth=='9') sMonth = 'September';
        else if(iMonth=='10') sMonth = 'October';
        else if(iMonth=='11') sMonth = 'November';
        else if(iMonth=='12') sMonth = 'December';

        String sConDate='';
        if(sMonth!=null && sYear!=null)
            sConDate = sMonth+', '+sYear;
        return sConDate;
    }  
 
public DateTime getGeneratedDate(){ return System.Now(); } //First Data Table
public List<Key_Accounts_Snapshot__c> getKeyAccountsSnapshot(){ return [Select Customer_Name__c,Segment__c,Segment_Formula__c,Superbrand__c,Superbrand_formula__c, Management_Engagements__c,Sales_Visits__c,CSD_Site_Visits__c,DIFOT_Customer_Required__c, DIFOT_Natsteel_Promised__c,Customer_Complains__c,Return_Loads__c,Urgent_Orders__c, No_of_Projects__c,No_of_Opportunities_Won__c,Contracted_Volume__c, Total_Quantity_MT__c,Rebar_Total_Quantity_MT__c,CAB_Total_Quantity_MT__c, WM_Total_Quantity_MT__c,BPC_Total_Quantity_MT__c,PCG_Total_Quantity_MT__c, D_S_Ratio__c,AR_Days__c from Key_Accounts_Snapshot__c WHERE CreatedDate=TODAY Order By Customer_Name__c LIMIT 28]; }
public List<KeyAccountPDF> snapshotResult = new List<KeyAccountPDF>();

//2nd data table public List <KeyAccountPDF> getKeyAccountsSnapshotYearly(){

AggregateResult[] groupedResults = [Select Customer_Name__c,MAX(Segment__c),MAX(Superbrand__c), SUM(Management_Engagements__c),SUM(Sales_Visits__c),SUM(CSD_Site_Visits__c),SUM(DIFOT_Customer_Required__c), SUM(DIFOT_Natsteel_Promised__c),SUM(Customer_Complains__c),SUM(Return_Loads__c),SUM(Urgent_Orders__c), SUM(No_of_Projects__c),SUM(No_of_Opportunities_Won__c),SUM(Contracted_Volume__c), SUM(Total_Quantity_MT__c),SUM(Rebar_Total_Quantity_MT__c),SUM(CAB_Total_Quantity_MT__c), SUM(WM_Total_Quantity_MT__c),SUM(BPC_Total_Quantity_MT__c),SUM(PCG_Total_Quantity_MT__c), SUM(D_S_Ratio__c),SUM(AR_Days__c) from Key_Accounts_Snapshot__c WHERE CreatedDate <=TODAY GROUP BY Customer_Name__c ORDER BY Customer_Name__c]; for (AggregateResult ar : groupedResults) { snapshotResult.add(new KeyAccountPDF(String.valueOf(ar.get('Customer_Name__c')), String.valueOf(ar.get('expr0')), String.valueOf(ar.get('expr1')), String.valueOf(ar.get('expr2')), String.valueOf(ar.get('expr3')), String.valueOf(ar.get('expr4')), String.valueOf(ar.get('expr5')), String.valueOf(ar.get('expr6')), String.valueOf(ar.get('expr7')), String.valueOf(ar.get('expr8')), String.valueOf(ar.get('expr9')), String.valueOf(ar.get('expr10')), String.valueOf(ar.get('expr11')), String.valueOf(ar.get('expr12')), String.valueOf(ar.get('expr13')), String.valueOf(ar.get('expr14')), String.valueOf(ar.get('expr15')), String.valueOf(ar.get('expr16')), String.valueOf(ar.get('expr17')), String.valueOf(ar.get('expr18')), String.valueOf(ar.get('expr19')), String.valueOf(ar.get('expr20')))); } return snapshotResult; } }

 

sfdcFanBoysfdcFanBoy
Any update on this please??
liron169liron169
Hello,

Try to load the page in the URL with same parameters,
to check if the problem is in the page or in the PDF.
sfdcFanBoysfdcFanBoy
Direct URL with PDF is working fine in browser. Only when it is sent through email it isn't opening.
liron169liron169

Hi,

 

Maybe this is the issue.

 

Found in SF documentation.

getContent

getContentAsPDF

 

 

This method can't be used in:

  • Triggers
  • Scheduled Apex
  • Batch jobs
  • Test methods
  • Apex email service

 

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_pages_pagereference.htm

 

 

liron169liron169

You can create Email template with component that include all the data (as in your current page).

Then I think in the code you can set the email field: templateId, to the ID of your template.

sfdcFanBoysfdcFanBoy
Thanks Liron169. I used component and visualforce email template.

The VF page is now embeded inside the email body. How can I make it as an attachment?
liron169liron169

Easy. Inside the email template write:

 

<messaging:attachment renderAs="PDF" filename="myPDFFile.pdf">

<html>   
    <body>
        <!-- Here should have all the data that should be in the PDF.....

can be component that generate all the data   -->
    </body>
</html>
   </messaging:attachment>

This was selected as the best answer
sfdcFanBoysfdcFanBoy

Thanks very much Liron169.  Worked perfect.

 

Here's the complete code for others to refer.

 

//Component Code
<apex:component controller="AccountPDF" access="Global" > /* VF CODE */ </apex:component> //Email Template Code <messaging:emailTemplate subject="Customers PDF" recipientType="User" relatedToType="Snapshot__c"> <messaging:htmlEmailBody > Please find attached the PDF. </messaging:htmlEmailBody> <messaging:attachment renderAs="PDF" filename="myPDFFile.pdf"> <c:Key_Customers_PDF /> </messaging:attachment> </messaging:emailTemplate>

 

Tyler McCartyTyler McCarty
I was getting the same error, I would get the email and the attachment but it wouldn't be coded as a PDF so it didn't know how to display the file. Try creating a list of attachments then adding the file to the list and adding the list to the email.
The following code works fine: 

public class GenerateEmail
{    
    public static void sendEmail()
    {   
        List<Messaging.EmailFileAttachment> emailAttachList=new List<Messaging.EmailFileAttachment>();
        
        Pagereference ref = page.YourPageName;
        ref.setRedirect(true);
        
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        Messaging.EmailFileAttachment fileAttachment = new Messaging.EmailFileAttachment();
        Blob b;
        
        try 
        {
             b = ref.getContentAsPDF();
        }
        catch (VisualforceException e) 
        {
            System.debug(e.getMessage()); 
            b = Blob.valueOf('No content in PDF');
        }
        fileAttachment.setBody(b);
        
        List<ID> EmailList = new List<ID>();
        List <Contact> contactList = new List <Contact>([Select Id, Email from contact where id = 'xxxxxxxxxx']);  /*change this because ID's differ from org to org, this was just for testing*/
         EmailTemplate template =  [SELECT Id, Name FROM EmailTemplate where name = 'OptionalEmailTemplate' LIMIT 1];
       
        for(Contact c : contactList)
        {
           EmailList.add(c.id);
        }
      

       // Create the email attachment
       fileAttachment.setFileName('YourFileName'+ date.today().day() + '_' + date.today().month() + '_' + date.today().year() + '.pdf');
       fileAttachment.setBody(b);
       emailAttachList.add(fileAttachment);
       if(emailAttachList!=null)
       {    
            email.setFileAttachments(emailAttachList);
       }
        
        email.setToAddresses(EmailList);
        email.setSubject('Test PDF Email');
        email.setPlainTextBody('This is a test email.');
        email.setTemplateId(template.id);
       
        try
        {
            Messaging.sendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});     
        }
        catch(exception e)
        {
            System.debug(e.getMessage());
        }
        
     }
}
James Robert 20James Robert 20

There is a new way to save emails as a PDF, that does not require any script or something like that. 

Follow this: https://www.cigatisolutions.com/blog/save-gmail-email-as-pdf/