Similar to how we can use apex to get the blob value of a VisualForce page, can we also do this on a VisualForce Email Template? We need to get the rendered template into an attachment record in Salesforce.
[SalesForce] Get VisualForce Email Template as Blob
Related Solutions
I don't think you can do it with pure email template, you'll need some Apex, as suggested in other answers.
<messaging:emailTemplate>
complains as soon as you'd try to stick <apex:repeat>
in there (for example to create <messaging:attachment>
nodes in a loop).
Even if you could - try referring to {!relatedTo.Attachments[0].Body}
somewhere (can be in the plaintextBody tag), you'll get an error:
Binary fields cannot be selected in join queries
I think the closest it can get is to create the links to attachments (and if I recall correctly - SF converts attachments > 3 MB to links anyway).
<messaging:emailTemplate subject="hello" recipientType="Contact" relatedToType="Opportunity">
<messaging:htmlEmailBody >
<p>This will list link to attachments... it's not a perfect solution but it's something.</p>
<apex:repeat value="{!relatedTo.Attachments}" var="a">
<p><a href="{!URLFOR($Action.Attachment.Download, a)}">{!a.Name}</a> ({!a.BodyLength} B)</p>
</apex:repeat>
</messaging:htmlEmailBody>
<messaging:plainTextEmailBody >
<apex:repeat value="{!relatedTo.Attachments}" var="a">
{!a.Name} {!a.ContentType} {!a.Body} <!-- this "Body" reference causes the compilation to fail -->
</apex:repeat>
</messaging:plainTextEmailBody>
<!--
<messaging:attachment filename="{!relatedTo.Attachments[0].Name}" renderAs="{!relatedTo.Attachments[0].ContentType}">
{!relatedTo.Attachments[0].Body} :(
</messaging:attachment>
-->
</messaging:emailTemplate>
OK, this could be the issue (having recently faced this myself)
Your database structure appears to be:
License__c
- Several
License_Property__c
each of which has a lookup relationship toLicense__c
You mentioned that you are using a workflow to fire the email alert that references the License__c
. The target of the workflow, is represented in the VF email template by relatedTo.id
- Per VF order of execution,
relatedTo.id
is passed as an attribute to the custom component and assigned to the custom controller'sm_licenseId
via thesetId()
method - The order of execution now has the component calling
getLines()
that callsInitialize()
to fetch the list ofLicense_property__c
So far, so good.
My hypothesis, and where I was bitten, is when you test the template in the VF Email Template editor, you already had built the License__c
and related License_Property__c
s. The template renders fine
But when you test via exercising the workflow, no License_property__c
s appear
A likely cause of this is that the workflow is triggered too soon - before the License_Property__c
are built by whatever process causes the workflow on License__c
to fire. Check your workflow entry criteria versus the state of the database.
Best Answer
One approach might be to factor the bulk of your Email Template code (which of course is just VF markup anyway) into a Visualforce Component. Thus enabling you to share it by referencing this component between a Visualforce Page (to enable you to capture it on your attachments) and Email Templates (for when your emailing). For example.
Your email template would look like this...
Your VF page would look like this...
Hope this helps!
Note: Note that Visualforce Components when delivered in Managed Packages are none editable, unlike Email Templates. You can work around this though, by copy and pasting the component code into a new one in the subscriber code and changing the template to point to the new component.