You need to sign in to do that
Don't have an account?
sc2510
Workflow fires but visual force email template with attachment is not sent
I added a field update to make sure the workflow runs when it should but the email still doesn't send. Removing the email attachements fixes the problem, does anyone know why this would be preventing it from sending? I've made sure all users have access to the report, apex controller and class, what am I missing?
Attachments (workflow email is sent when this is removed, I've tried just including one attachment but it still doesn't work)
Email Template
Class
Component
Attachments (workflow email is sent when this is removed, I've tried just including one attachment but it still doesn't work)
<messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.xls"> <c:reportexport reportId="00O30000008AUFV" format="xls" params="{!left(relatedTo.id,15)}"/> </messaging:attachment> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.csv"> <c:reportexport reportId="00O30000008AUFV" format="csv" prettify="false" params="{!left(relatedTo.id,15)}" /> </messaging:attachment> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.htm"> <c:reportexport reportId="00O30000008AUFV" format="printable" params="{!left(relatedTo.id,15)}" /> </messaging:attachment> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.pdf" renderAs="pdf"> <style> .headerRow {background-color:#cbb54c} .grandTotal {background-color:#ede5c1} </style> <c:reportexport reportId="00O30000008AUFV" format="printable" params="{!left(relatedTo.id,15)}" /> </messaging:attachment>
Email Template
<messaging:emailTemplate subject="{!relatedTo.Name} - Opportunity CLOSED WON" recipientType="User" relatedToType="Opportunity"> <messaging:htmlEmailBody > <table cellpadding="5" cellspacing="0" border="0" width="700" style="border:1px solid #5C6F7C;" align="center"> <tr> <td colspan="3" align="center" height="60" bgcolor='{! IF(relatedTo.Type="New Client","#faf2dc", IF(relatedTo.Type="Upsell","#bed7db",IF(relatedTo.Type="Renewal","#c1cae3","#d5dde2"))) }' style="border-bottom:1px solid #005295;"><p style="font-family:Arial, Helvetica, sans-serif; font-size:14px;"><b style='font-size:18px; color:{! IF(relatedTo.Type="New Client","#ceb54b", IF(relatedTo.Type="Upsell","#006a72",IF(relatedTo.Type="Renewal","#005395","#5c707c")))}'>Business Development</b><br />{!relatedTo.Type} — {!MONTH(relatedTo.Start_Date_of_Services__c)}/{!DAY(relatedTo.Start_Date_of_Services__c)}/{!YEAR(relatedTo.Start_Date_of_Services__c)}</p></td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Corporation/Facility Name:</b></td> <td width="478"><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px"><a href="https://na1.salesforce.com/{!relatedTo.id}">{!relatedTo.Account_name__c}</a></span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Sales Contact:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px"><a href="https://na1.salesforce.com/{!relatedTo.Main_Opportunity_Contact__c}">{!relatedTo.Sales_name__c}</a><i>{!relatedTo.Sales_title__c}</i><br /><a href="mailto:{!relatedTo.Sales_email__c}">{!relatedTo.Sales_email__c}</a><br />{!relatedTo.Sales_phone__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Billing Contact:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.Billing_Contact2__c}<br />{!relatedTo.Billing_Contact_Phone__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Onboarding/Corporate Contact:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.Onboarding_Corporate_Contact__c}<br /><a href="mailto:{!relatedTo.Onboarding_Corporate_Contact_Email__c}">{!relatedTo.Onboarding_Corporate_Contact_Email__c}</a><br />{!relatedTo.Onboarding_Corporate_Contact_Phone__c}<br /> Preferred Contact Method: <b>{!relatedTo.Onboarding_Corporate_Preferred_Contact__c}</b></span></td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">MDS Vendor:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{!relatedTo.MDS_Vendor__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Interface:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.Interface__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Facility Count:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{!SUBSTITUTE(text(relatedTo.Facility_Count__c),".0","")}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Contract Amount:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">${!relatedTo.Contract_Amount__c}</span></td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td width="200" align="right"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">PointRight Team</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px"></span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">NAM:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.PointRight_BAM__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Clinician:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.PointRight_Clinician__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Sales Rep:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.PointRight_Sales__c}</span></td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Opportunity Close Date:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{!MONTH(relatedTo.CloseDate)}/{!DAY(relatedTo.CloseDate)}/{!YEAR(relatedTo.CloseDate)}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Start Date of Services:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{!MONTH(relatedTo.Start_Date_of_Services__c)}/{!DAY(relatedTo.Start_Date_of_Services__c)}/{!YEAR(relatedTo.Start_Date_of_Services__c)}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Contract Type:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{! relatedTo.Contract_Type__c}{!IF(relatedTo.Contract_Type__c="Other",": ", IF(relatedTo.Contract_Type__c="other",": ",""))} {!relatedTo.Contract_Type_Other__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Invoice Type:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.Invoice_Type__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Invoice Frequency:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.Invoice_Frequency__c}</span></td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Comments:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{!relatedTo.Comments__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Invoicing Notes:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px">{!relatedTo.Invoicing_Notes__c}</span></td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:14px">Lead Sources</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:14px"></span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Primary:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.LeadSource}<br /> {!relatedTo.Primary_Lead_Source_TXT__c}</span></td> </tr> <tr> <td width="200" align="right" valign="top"><b style="font-family:Arial, Helvetica, sans-serif; font-size:12px">Secondary:</b></td> <td><span style="font-family:Arial, Helvetica, sans-serif; font-size:12px">{!relatedTo.Secondary_Lead_Source__c}<br /> {!relatedTo.Secondary_Lead_Source_TXT__c}</span></td> </tr> <tr> <td colspan="2"> </td> </tr> </table> </messaging:htmlEmailBody> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.xls"> <c:reportexport reportId="00O30000008AUFV" format="xls" params="{!left(relatedTo.id,15)}"/> </messaging:attachment> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.csv"> <c:reportexport reportId="00O30000008AUFV" format="csv" prettify="false" params="{!left(relatedTo.id,15)}" /> </messaging:attachment> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.htm"> <c:reportexport reportId="00O30000008AUFV" format="printable" params="{!left(relatedTo.id,15)}" /> </messaging:attachment> <messaging:attachment filename="Opportunity Products - {!relatedTo.Name}.pdf" renderAs="pdf"> <style> .headerRow {background-color:#cbb54c} .grandTotal {background-color:#ede5c1} </style> <c:reportexport reportId="00O30000008AUFV" format="printable" params="{!left(relatedTo.id,15)}" /> </messaging:attachment> </messaging:emailTemplate>
Class
/* Allows programmatic retrieve of data generated by any report for further processing in Apex or attaching to emails. Uses Page.getContent() by default but in future/scheduled context will fall back to REST GET (remember to add "Remote Site Setting" if you plan to use it like that). Use with care, you might still hit heap size limits with bigger reports! Of course it can fail anytime Salesforce changes the layout of report pages, their output or parameters that can be passed via URL etc. */ // TODO: add support for query string pv0 etc. params for runtime filtering? public with sharing class ReportExportController { public static final Set<String> validEncodings = new Set<String>{'UTF-8','MS932','Shift_JIS','GB18030','GB2312','Big5','EUC_KR','UTF-16','Big5-HKSCS','x-SJIS_0213'}; public static final Set<String> validformats = new Set<String>{'printable','csv','xls'}; public static final Set<String> validShowDetails = new Set<String>{'yes','no',null}; public static String mockOutput; // to be used in unit test. getContent() can't be called in test, // REST way means need to make a mock anyway (but then you'd need remote site setting for both production and all possible sandboxes...) // Basic options. public Id reportId {get;set;} public String format {get;set;} // See list above for available options public String params {get;set;} // Add parameters to the report public Boolean prettify {get;set;} /* If set we'll attempt to return only the core info without: - headers: who run it, when, which company, what's the report title, filters used - footers: "Confidential Information - Do Not Distribute" etc. */ // Option for format = 'printable' only public String showDetails {get;set;} // like "show details" button. See list above for available options; null = fallback to however the report was saved // Option for format 'csv' and 'xls' public String encoding {get;set;} // See list above for available options private String requestUrl, output; private Boolean restRequestNeeded; public ReportExportController(){ prettify = true; restRequestNeeded = System.isFuture() || System.isScheduled(); // System.isBatch() too? } public String getOutput(){ if(requestUrl == null) { getRequestUrl(); } fetchData(); if(prettify && output != null && output.length() > 0){ prettify(); } return output; } public String getRequestUrl(){ sanitizeInput(); requestUrl = '/' + reportId + '?'; if(params != null){ requestUrl += 'pv0=' + params + '&'; } if(format == 'printable'){ requestUrl += 'excel=1' + (showDetails != null ? '&details=' + showDetails : ''); } else { //requestUrl += 'export=1&xf=' + format + '&enc=' + encoding; requestUrl += 'export=1&xf=' + format + '&enc=UTF-8'; } if(restRequestNeeded) { requestUrl = URL.getSalesforceBaseUrl().toExternalForm().replace('http:', 'https:') + requestUrl; } return requestUrl; } private void sanitizeInput(){ if(reportId == null){ throw new ReportExportException('Missing argument: reportId'); } else if(!String.valueOf(reportId).startsWith('00O')) { // Length - based check can be skipped - it will fail on attempt to assign too long string to Id variable throw new ReportExportException('Suspicious reportId: ' + reportId + '. Were you trying to export something other than a report?'); } if(encoding == null || !validEncodings.contains(encoding)){ encoding = 'UTF-8'; } if(format == null || !validformats.contains(format)){ format = 'xls'; } if(!validShowDetails.contains(showDetails)){ showDetails = null; } } private void fetchData(){ if(Test.isRunningTest()){ output = mockOutput; } else if(restRequestNeeded){ HttpRequest req = new HttpRequest(); req.setEndpoint(requestUrl); req.setMethod('GET'); req.setHeader('Cookie','sid=' + UserInfo.getSessionId()); output = new Http().send(req).getBody(); } else { output = new PageReference(requestUrl).getContent().toString(); } } private void prettify(){ Integer startIndex = 0; Integer stopIndex = output.length(); if(format == 'csv'){ stopIndex = output.lastIndexOf('\n\n\n'); // "lastindexOf" because we look for last occurence of 3 x "Enter". So it should work even if there's data in report (textarea?) that contains such line } else { String endToken = ''; if(format == 'xls'){ startIndex = output.indexOf('<table>'); endToken = '</table>'; } else if(format == 'printable'){ startIndex = output.indexOf('<div id="fchArea">'); endToken = '</table>\n</div>'; } stopIndex = output.lastIndexOf(endToken) + endToken.length(); } if(startIndex != -1 && stopIndex != -1) { output = output.substring(startIndex, stopIndex); } } public class ReportExportException extends Exception{} }
Component
<apex:component controller="ReportExportController" access="global"> <apex:attribute name="reportId" description="Id of the report to be retrieved." type="Id" assignTo="{!reportId}"/> <apex:attribute name="format" description="'printable', 'csv' or 'xls'. Corresponds to 'Printable view' or 'Export Details' options." type="String" assignTo="{!format}"/> <apex:attribute name="params" description="Optional: Add variables to the report" type="String" assignTo="{!params}"/> <apex:attribute name="prettify" description="Select if you want to try cutting out headers and footers." type="Boolean" default="true" assignTo="{!prettify}"/> <apex:attribute name="encoding" description="Text encoding (UTF-8 etc)." type="String" default="UTF-8" assignTo="{!encoding}" /> <apex:attribute name="showDetails" description="If 'printable' is used - choose if you want to override report's show/hide details setting. Use 'yes' or 'no'" type="String" assignTo="{!showDetails}" /> <!-- {!requestUrl} --> <apex:outputText value="{!output}" escape="false" /> </apex:component>
sc2510
The email template with attachments works fine when I 'send test and verify merge fields'