Monday, 27 October 2014

Send Email with Generated PDF as attachment from Trigger

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 ofPageReference class and use returned blob data as a attachment in Email.
However, 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 you 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
1<apex:page renderAs="PDF">
2  <!-- Begin Default Content REMOVE THIS -->
3  <h1>Congratulations</h1>
4  This is your new Page
5  <!-- End Default Content REMOVE THIS -->
6</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 :
1/**
2*   Created By  :   Jitendra Zaa
3*   Description :   Apex based REST API which exposes POST method to send Email
4*/
5@RestResource(urlMapping='/sendPDFEmail/*')
6Global class GETPDFContent{
7     @HttpPost
8    global static void sendEmail(String EmailIdCSV, String Subject, String body) {
9 
10    List<String> EmailIds = EmailIdCSV.split(',');
11 
12        PageReference ref = Page.PDF_DEMO;
13        Blob b = ref.getContentAsPDF();
14 
15        Messaging.SingleEmailMessage email = newMessaging.SingleEmailMessage();
16 
17        Messaging.EmailFileAttachment efa1 = newMessaging.EmailFileAttachment();
18        efa1.setFileName('attachment_WORK.pdf');
19        efa1.setBody(b);
20 
21        String addresses;
22        email.setSubject( Subject +String.valueOf(DateTime.now()));
23        email.setToAddresses( EmailIds  );
24        email.setPlainTextBody(Body);
25        email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa1});
26        Messaging.SendEmailResult [] r = Messaging.sendEmail(newMessaging.SingleEmailMessage[] {email});
27 
28    }
29}
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
1/**
2*   Created By  :   Jitendra Zaa
3*   Description :   This class exposes @future method to send VF page rendered as PDF as attachment in Email
4*/
5public class SendVFAsAttachment{
6 
7    @future(callout=true)
8    public static void sendVF(String EmailIdCSV, String Subject,String body,String userSessionId)
9    {
10        //Replace below URL with your Salesforce instance host
12        HttpRequest req = new HttpRequest();
13        req.setEndpoint( addr );
14        req.setMethod('POST');
15        req.setHeader('Authorization''OAuth ' + userSessionId);
16        req.setHeader('Content-Type','application/json');
17 
18        Map<String,String> postBody = new Map<String,String>();
19        postBody.put('EmailIdCSV',EmailIdCSV);
20        postBody.put('Subject',Subject);
21        postBody.put('body',body);
22        String reqBody = JSON.serialize(postBody);
23 
24        req.setBody(reqBody);
25        Http http = new Http();
26        HttpResponse response = http.send(req);
27    }
28}
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“.
1req.setHeader('Content-Type','application/json');
2 
3Map<String,String> postBody = new Map<String,String>();
4postBody.put('EmailIdCSV',EmailIdCSV);
5postBody.put('Subject',Subject);
6postBody.put('body',body);
7String reqBody = JSON.serialize(postBody);
Writing Trigger:
1/**
2*   Created By  :   Jitendra Zaa
3*   Description :   This Trigger calls @future method to send VF page rendered as PDF as attachment in Email
4*   Note        :   Make sure that this Trigger does not call Future methods more than 10 times.
5*/
6trigger SampleTrigger on Lead (before insert) {
7    SendVFAsAttachment.sendVF('emailaddress1@email.com,emailaddress2@email.com','Sample Test from Trigger',
8    'Sample Email Body',UserInfo.getSessionId());
9}
From above sample code, we are calling static method asynchronously, which in turn calling REST API to send Email with Visualforce as attachment.

No comments:

Post a Comment