There may be scenario in Salesforce that you need to send a Visualforce page rendered as PDF as a part of Email Attachment. This will be very easy if you want to perform this using Controller or Extension class, we just have to call getContentAsPDF() method of PageReference class and use returned blob data as a attachment in Email.
Update – 21 Oct 2015 (Winter 16)
After Winter 16 release, this solution will not work as getContent() method is treated as callout and if we try to call it from Async Apex or Rest API in this case, it will not return pdf content.
This solution will only work for you if you have not enabled critical update “PageReference getContent() and getContentAsPDF() Methods Treated as Callouts” in your Salesforce organization.
Note : If this solution is not working for you then try this.
If we are talking about achieving same in Trigger then it would be problem. Trigger does not support getContent() method of PageReference class. If you are thinking to use getContent() in future call then again we are not lucky, because @future methods does not support it. Also Apex job doesn’t support this method.
Now, I hope you understood that in which situation we are 🙂
So, In this article, I am going to explain how to resolve this issue. Not exactly resolve but workaround for above problem.
Solution is very simple, We will expose apex method as a REST API. Code for sending email will be written in APEX based REST API and our Trigger will call this method asynchronously using @future annotation.
Sample Visualforce Page, page Name – “PDF_Demo”
<apex:page renderAs="PDF" > <!-- Begin Default Content REMOVE THIS -- > <h1 >Congratulations </h1 > This is your new Page <!-- End Default Content REMOVE THIS -- > </apex:page >
Lets assume that above Visualforce page needs to be send as a part of attachment.
Creating APEX based REST API with POST Method :
/** * Created By : Jitendra Zaa * Description : Apex based REST API which exposes POST method to send Email */ @RestResource(urlMapping='/sendPDFEmail/*') Global class GETPDFContent{ @HttpPost global static void sendEmail(String EmailIdCSV, String Subject, String body) { List&lt;String&gt; EmailIds = EmailIdCSV.split(','); PageReference ref = Page.PDF_DEMO; Blob b = ref.getContentAsPDF(); Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); Messaging.EmailFileAttachment efa1 = new Messaging.EmailFileAttachment(); efa1.setFileName('attachment_WORK.pdf'); efa1.setBody(b); String addresses; email.setSubject( Subject +String.valueOf(DateTime.now())); email.setToAddresses( EmailIds ); email.setPlainTextBody(Body); email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa1}); Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); } }
In above code, we have created APEX based REST API with POST method. We are simply getting content of Visualforce rendered as PDF with method “getContentAsPDF()” and setting up this in object of “Messaging.EmailFileAttachment”.
REST API created using Apex class can be accessed from URL “https://<YOUR_SALESFORCE_INSTANCE>/services/apexrest/<RESTURL>”
In below part of code, we will be consuming REST API recently created
/** * Created By : Jitendra Zaa * Description : This class exposes @future method to send VF page rendered as PDF as attachment in Email */ public class SendVFAsAttachment{ @future(callout=true) public static void sendVF(String EmailIdCSV, String Subject,String body,String userSessionId) { //Replace below URL with your Salesforce instance host String addr = 'https://shivasoft--shiva1.cs6.my.salesforce.com/services/apexrest/sendPDFEmail'; HttpRequest req = new HttpRequest(); req.setEndpoint( addr ); req.setMethod('POST'); req.setHeader('Authorization', 'OAuth ' + userSessionId); req.setHeader('Content-Type','application/json'); Map&lt;String,String&gt; postBody = new Map&lt;String,String&gt;(); postBody.put('EmailIdCSV',EmailIdCSV); postBody.put('Subject',Subject); postBody.put('body',body); String reqBody = JSON.serialize(postBody); req.setBody(reqBody); Http http = new Http(); HttpResponse response = http.send(req); } }
Note : Please make sure you have added URL of your salesforce in “Remote Site Settings“, else you will not be able to make REST API call.
Question : How do we set Body for POST method in Apex based REST API or How do we supply argument in POST method ?
Answer : As you can see in above code sample, we have to supply JSON as a Request Body and set Header ContentType as “application/json“.
req.setHeader('Content-Type','application/json'); Map&lt;String,String&gt; postBody = new Map&lt;String,String&gt;(); postBody.put('EmailIdCSV',EmailIdCSV); postBody.put('Subject',Subject); postBody.put('body',body); String reqBody = JSON.serialize(postBody);
Writing Trigger:
/** * Created By : Jitendra Zaa * Description : This Trigger calls @future method to send VF page rendered as PDF as attachment in Email * Note : Make sure that this Trigger does not call Future methods more than 10 times. */ trigger SampleTrigger on Lead (before insert) { SendVFAsAttachment.sendVF('emailaddress1@email.com,emailaddress2@email.com','Sample Test from Trigger', 'Sample Email Body',UserInfo.getSessionId()); }
From above sample code, we are calling static method asynchronously, which in turn calling REST API to send Email with Visualforce as attachment.
Leave a Reply