Integrating Email with Visualforce. salesforce Visualforce Developer Guide
Annonce
Annonce
CHAPTER 14 Integrating Email with Visualforce
Visualforce can be used to send email to any of your contacts, leads, or other recipients. It is also possible to create reusable email templates that take advantage of Visualforce's ability to iterate over your Salesforce records. The following topics explain how:
•
Sending an Email with Visualforce
•
Sending an Email with Visualforce
It is possible to send email using Visualforce by creating a
to deliver the message. The Apex
Messaging.SingleEmailMessage
class handles the outbound email functionality available to Salesforce.
The following topics demonstrate a number of features available when sending email through Visualforce:
•
Creating a Custom Controller with the Messaging Class
•
Creating a Custom Controller with the Messaging Class
At minimum, a custom controller that uses the Apex
Messaging
namespace needs a subject, a body, and a recipient for the email.
You will need a page that acts as a form to fill out the subject and body and deliver the email.
Create a new page called sendEmailPage
and use the following code:
<apex:page controller= "sendEmail" >
<apex:messages />
<apex:pageBlock title= "Send an Email to Your
{!account.name} Representatives ">
<p >Fill out the fields below to test how you might send an email to a user.
</p >
<br />
<apex:dataTable value= "{!account.Contacts}" var= "contact" border= "1" >
<apex:column >
<apex:facet name= "header" >Name </apex:facet >
{!contact.Name}
</apex:column >
<apex:column >
<apex:facet name= "header" >Email </apex:facet >
{!contact.Email}
</apex:column >
</apex:dataTable >
<apex:form >
<br /> <br />
<apex:outputLabel value= "Subject" for= "Subject" />: <br />
194
Integrating Email with Visualforce Creating a Custom Controller with the Messaging Class
<apex:inputText value= "{!subject}" id= "Subject" maxlength= "80" />
<br /> <br />
<apex:outputLabel value= "Body" for= "Body" />: <br />
<apex:inputTextarea value= "{!body}" id= "Body" rows= "10" cols= "80" />
<br /> <br /> <br />
<apex:commandButton value= "Send Email" action= "{!send}" />
</apex:form >
</apex:pageBlock >
</apex:page >
Notice in the page markup that the account ID is retrieved from the URL of the page. For this example to render properly, you must associate the Visualforce page with a valid account record in the URL. For example, if
001D000000IRt53
is the account ID, the resulting URL should be: https://
Salesforce_instance
/apex/sendEmailPage?id=001D000000IRt53
Displaying Field Values with Visualforce
on page 18 has more information about retrieving the ID of a record.
The following code creates a controller named sendEmail
that implements the
Messaging.SingleEmailMessage
class, and uses the contacts related to an account as recipients: public class sendEmail { public String subject { get; set; } public String body { get; set; } private final Account account;
// Create a constructor that populates the Account object public sendEmail() {
} account = [select Name, (SELECT Contact.Name, Contact.Email FROM Account.Contacts) from Account where id = :ApexPages.currentPage().getParameters().get( 'id' )]; public Account getAccount() { return account;
} public PageReference send() {
// Define the email
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
String addresses; if (account.Contacts[0].Email != null )
{ addresses = account.Contacts[0].Email;
// Loop through the whole list of contacts and their emails for ( Integer i = 1; i < account.Contacts.size(); i++)
{ if (account.Contacts[i].Email != null )
{ addresses += ':' + account.Contacts[i].Email;
}
}
}
195
Integrating Email with Visualforce Creating a Custom Controller with the Messaging Class
String [] toAddresses = addresses.split( ':' , 0);
// Sets the paramaters of the email email.setSubject( subject ); email.setToAddresses( toAddresses ); email.setPlainTextBody( body );
// Sends the email
Messaging.SendEmailResult [] r =
Messaging.sendEmail( new Messaging.SingleEmailMessage[] {email});
}
} return null ;
Notice in the controller that:
•
The subject and body of the email are set through a separate Visualforce page and passed into the controller.
•
The method that sends the email is called send()
. This name must match the name of the action for the Visualforce button that sends the email.
•
The recipients of the email, that is, the email addresses stored in toAddresses[]
, come from the addresses of the contacts available in an associated account. When compiling a list of recipients from contacts, leads, or other records, it is a good practice to loop through all the records to verify that an email address is defined for each. The account ID is retrieved from the URL of the page.
196
Integrating Email with Visualforce
Example of the Form on sendEmailPage
Creating an Email Attachment
SEE ALSO:
Apex Developer Guide: Outbound Email
Creating an Email Attachment
If you want to add an attachment to your email, you will need to add only a few lines of code to your custom controller. Email attachments are
Blob
file types. To create an attachment, you need to use the Apex
Messaging.EmailFileAttachment
class. You must define both the file name and the content of an
EmailFileAttachment
object.
Adding a PDF Attachment
The following example demonstrates how to transform a
PageReference
to a Visualforce page rendered as a PDF into an email attachment. First, create a page called attachmentPDF
:
<apex:page standardController= "Account" renderAs= "PDF" >
<h1 >Account Details </h1 >
197
Integrating Email with Visualforce Creating an Email Attachment
<apex:panelGrid columns= "2" >
<apex:outputLabel for= "Name" value= "Name" />
<apex:outputText id= "Name" value= "{!account.Name}" />
<apex:outputLabel for= "Owner" value= "Account Owner" />
<apex:outputText id= "Owner" value= "{!account.Owner.Name}" />
<apex:outputLabel for= "AnnualRevenue" value= "Annual Revenue" />
<apex:outputText id= "AnnualRevenue" value= "{0,number,currency}" >
<apex:param value= "{!account.AnnualRevenue}" />
</apex:outputText >
<apex:outputLabel for= "NumberOfEmployees" value= "Employees" />
<apex:outputText id= "NumberOfEmployees" value= "{!account.NumberOfEmployees}" />
</apex:panelGrid >
</apex:page >
Note:
See
Best Practices for Rendering PDF Files
on page 345 for details of which components are recommended for use in PDF attachments.
Next, create the
EmailFileAttachment
object in the send()
method of your custom controller. The following examples must be placed before calling
Messaging.sendEmail
:
// Reference the attachment page, pass in the account ID
PageReference pdf = Page.attachmentPDF; pdf.getParameters().put( 'id' ,( String )account.id); pdf.setRedirect( true );
// Take the PDF content
Blob b = pdf.getContent();
// Create the email attachment
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment(); efa.setFileName( 'attachment.pdf' ); efa.setBody(b);
If your
SingleEmailMessage
object is named email
, then you associate the attachment like this: email.setFileAttachments( new Messaging.EmailFileAttachment[] {efa});
Defining a Custom Component as an Attachment
By creating a custom component and using it on the Visualforce email form and to render the PDF for the email, users can see a preview of the content they are trying to send.
The following markup defines a custom component named attachment
that represents the attachment for the email:
<apex:component access= "global" >
<h1 >Account Details </h1 >
<apex:panelGrid columns= "2" >
198
Integrating Email with Visualforce Creating an Email Attachment
<apex:outputLabel for= "Name" value= "Name" />
<apex:outputText id= "Name" value= "{!account.Name}" />
<apex:outputLabel for= "Owner" value= "Account Owner" />
<apex:outputText id= "Owner" value= "{!account.Owner.Name}" />
<apex:outputLabel for= "AnnualRevenue" value= "Annual Revenue" />
<apex:outputText id= "AnnualRevenue" value= "{0,number,currency}" >
<apex:param value= "{!account.AnnualRevenue}" />
</apex:outputText >
<apex:outputLabel for= "NumberOfEmployees" value= "Employees" />
<apex:outputText id= "NumberOfEmployees" value= "{!account.NumberOfEmployees}" />
</apex:panelGrid >
</apex:component >
Replace your attachmentPDF
page like this:
<apex:page standardController= "account" renderAs= "PDF" >
<c:attachment/ >
</apex:page >
Then add the custom component to render at the bottom of your previous sendEmailPage
:
<apex:pageBlock title= "Preview the Attachment for {!account.name}" >
<c:attachment/ >
</apex:pageBlock >
If you want to make changes to both the attachment and the preview, the attachment
custom component needs to be modified in only one location.
Example: Sending an Email with an Attachment
The following example shows the
with a custom component that adds a Visualforce page as an attachment. First, the controller: public class sendEmail { public String subject { get; set; } public String body { get; set; } private final Account account;
// Create a constructor that populates the Account object public sendEmail() { account = [SELECT Name,
(SELECT Contact.Name, Contact.Email FROM Account.Contacts)
FROM Account
WHERE Id = :ApexPages.currentPage().getParameters().get( 'id' )];
} public Account getAccount() { return account;
}
199
Integrating Email with Visualforce Creating an Email Attachment public PageReference send() {
// Define the email
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
// Reference the attachment page and pass in the account ID
PageReference pdf = Page.attachmentPDF; pdf.getParameters().put('id',(String)account.id); pdf.setRedirect(true);
// Take the PDF content
Blob b = pdf.getContent();
// Create the email attachment
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment(); efa.setFileName('attachment.pdf'); efa.setBody(b);
String addresses; if (account.Contacts[0].Email != null ) { addresses = account.Contacts[0].Email;
// Loop through the whole list of contacts and their emails for ( Integer i = 1; i < account.Contacts.size(); i++) { if (account.Contacts[i].Email != null ) { addresses += ':' + account.Contacts[i].Email;
}
}
}
String [] toAddresses = addresses.split( ':' , 0);
// Sets the paramaters of the email email.setSubject( subject ); email.setToAddresses( toAddresses ); email.setPlainTextBody( body );
email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});
// Sends the email
Messaging.SendEmailResult [] r =
Messaging.sendEmail( new Messaging.SingleEmailMessage[] {email}); return null ;
}
}
Next, the Visualforce page that sends the email:
<apex:page controller= "sendEmail" >
<apex:messages/ >
<apex:pageBlock title= "Send an Email to Your {!account.name} Representatives" >
<p >Fill out the fields below to test how you might send an email to a user.
</p >
<apex:dataTable value= "{!account.Contacts}" var= "contact" border= "1" >
<apex:column >
200
Integrating Email with Visualforce Visualforce Email Templates
<apex:facet name= "header" >Name </apex:facet >
{!contact.Name}
</apex:column >
<apex:column >
<apex:facet name= "header" >Email </apex:facet >
{!contact.Email}
</apex:column >
</apex:dataTable >
<apex:form > <br/ > <br/ >
<apex:outputLabel value= "Subject" for= "Subject" />: <br/ >
<apex:inputText value= "{!subject}" id= "Subject" maxlength= "80" />
<br/ > <br/ >
<apex:outputLabel value= "Body" for= "Body" />: <br/ >
<apex:inputTextarea value= "{!body}" id= "Body" rows= "10" cols= "80" />
<br/ > <br/ >
<apex:commandButton value= "Send Email" action= "{!send}" />
</apex:form >
</apex:pageBlock >
<apex:pageBlock title="Preview the Attachment for {!account.name}">
<c:attachment/>
</apex:pageBlock>
</apex:page >
SEE ALSO:
Apex Developer Guide: EmailFileAttachment Class
Visualforce Email Templates
Developers and administrators can use Visualforce to create email templates. The advantage of using Visualforce over standard HTML email templates is that Visualforce gives you the ability to perform advanced operations on data that is sent to a recipient.
Although Visualforce email templates use standard Visualforce components, they are not created in the same way. Visualforce email templates always use components that are prefaced with the messaging
namespace. In addition:
•
All Visualforce email templates must be contained within a single
<messaging:emailTemplate >
tag. This is analogous to regular Visualforce pages being defined within a single
<apex:page >
tag.
•
The
<messaging:emailTemplate >
tag must contain either a single
<messaging:htmlEmailBody >
tag or a single
<messaging:plainTextEmailBody >
tag.
•
Several standard Visualforce components are not available for use within
<messaging:emailTemplate >
. These include
<apex:detail >
,
<apex:pageBlock >
and all related pageBlock
components, and all input components such as
<apex:form >
. If you attempt to save a Visualforce email template with these components, an error message displays.
The following topics provide more details:
•
Creating a Visualforce Email Template
•
Using a Custom Stylesheet in a Visualforce Email Template
201
Integrating Email with Visualforce Creating a Visualforce Email Template
•
•
Using Custom Controllers within Visualforce Email Templates
Creating a Visualforce Email Template
1. Do one of the following:
•
If you have permission to edit public templates, from Setup, enter
Email Templates
in the
Quick Find
box, then select Email Templates.
•
If you don’t have permission to edit public templates, go to your personal settings. Enter
Templates
in the
Quick Find box, then select Email Templates or My Templates—whichever one appears.
2. Click New Template.
3. Choose
Visualforce
and click Next.
You can’t send a mass email using a Visualforce email template.
4. Choose a folder in which to store the template.
5. To make the template available for use, select the
Available For Use
checkbox.
6. Enter a name in
Email Template Name
.
7. If necessary, change the
Template Unique Name
. This unique name refers to the component when you use the Force.com
API. In managed packages, this unique name prevents naming conflicts in package installations. This name can contain only underscores and alphanumeric characters, and must be unique in your org. It must begin with a letter, not include spaces, not end with an underscore, and not contain two consecutive underscores. With the
Template Unique Name
field, you can change certain components’ names in a managed package and the changes are reflected in a subscriber’s organization.
8. If desired, choose a different character set from the
Encoding
drop-down list.
9. Enter a description for the template. Both template name and description are for your internal use only.
10. Enter a subject line for your template in
Email Subject
.
11. In the
Recipient Type
drop-down list, select the type of recipient to receive email created from the template.
12. If desired, in the
Related To Type
drop-down list, select the object from which the template retrieves merge field data.
13. Click Save.
14. On the Viewing Email Templates page, click Edit Template.
15. Enter markup text for your Visualforce email template.
Note: If you are including an image, we recommend uploading it to the Documents tab to reference the copy of the image on our server. For example:
<apex:image id= "Logo" value= " https://
yourInstance
.salesforce.com/servlet/servlet.ImageServer?
id=015D0000000Dpwc&oid=00DD0000000FHaG&lastMod=127057656800 " height= "64" width= "64" />
16. To specify the version of Visualforce and the API used with this email template, click Version Settings. If you’ve installed managed packages from the AppExchange, you can also specify which version of each managed package to use with this email template.
Generally, use the default value for all versions, to associate the email template with the most recent version of Visualforce, the API, and each managed package. To maintain specific behavior, you can specify an older version of Visualforce and the API. To access components or functionality that differ from the most recent package version, you can specify an older version of a managed package.
202
Integrating Email with Visualforce Creating a Visualforce Email Template
17. To view the details of the template, click Save. To continue editing your template, click Quick Save. Your Visualforce markup must be valid before you can save your template.
Note: The maximum size of a Visualforce email template is 1 MB.
You can’t send a mass email using a Visualforce email template. The
{!Receiving_User.field_name}
and
{!Sending_User.field_name}
merge fields work only for mass email and are unavailable in Visualforce email templates.
The following example shows how you can define a Visualforce email template that displays all the cases associated with a contact. The example uses an
<apex:repeat >
tag to iterate through all the cases related to a contact and incorporate them into the body of the template:
<messaging:emailTemplate recipientType= "Contact" relatedToType= "Account" subject= "Case report for Account: {!relatedTo.name}" language= "{!recipient.language__c}" replyTo= "[email protected]" >
<messaging:htmlEmailBody >
<html >
<body >
<p >Dear {!recipient.name}, </p >
<p >Below is a list of cases related to {!relatedTo.name}.
</p >
<table border= "0" >
<tr >
<th >Case Number </th > <th >Origin </th >
<th >Creator Email </th > <th >Status </th >
</tr >
<apex:repeat var= "cx" value= "{!relatedTo.Cases}" >
<tr >
<td > <a href =
"https://na1.salesforce.com/{!cx.id}" >{!cx.CaseNumber}
</a > </td >
<td >{!cx.Origin} </td >
<td >{!cx.Contact.email} </td >
<td >{!cx.Status} </td >
</tr >
</apex:repeat >
</table >
<p/ >
<center >
<apex:outputLink value= "http://www.salesforce.com" >
For more detailed information login to Salesforce.com
</apex:outputLink >
</center >
</body >
</html >
</messaging:htmlEmailBody >
</messaging:emailTemplate >
Notice the following about the markup:
203
Integrating Email with Visualforce Using a Custom Stylesheet in a Visualforce Email Template
•
The attributes recipientType
and relatedToType
act as controllers for the email template. With them you can access the same merge fields that are available to other standard controllers. The recipientType
attribute represents the recipient of the email. The relatedToType
attribute represents the record to associate with the email.
•
The
<messaging:htmlEmailBody >
component can include a mix of Visualforce markup and HTML. The
<messaging:plainTextEmailBody >
component can only include Visualforce markup and plain text.
•
To translate Visualforce email templates based on recipients’ or related objects’ languages, use the
<messaging:emailTemplate >
tag's language
attribute (valid values: Salesforce supported language keys, for example,
“en-US”). The language attribute accepts merge fields from the email template's recipientType
and relatedToType attributes. You create custom language fields for use in the merge fields. The Translation Workbench is required to translate email templates. The example uses a merge field to obtain a language
attribute for the contact receiving the email.
SEE ALSO:
Using a Custom Stylesheet in a Visualforce Email Template
Using a Custom Stylesheet in a Visualforce Email Template
By default, Visualforce email templates always use the standard look and feel of other Salesforce components. However, you can extend or overwrite these styles by defining your own stylesheet.
Unlike other Visualforce pages, Visualforce email templates cannot use referenced
. Although the CSS appears to render in the email template preview pane, it does not appear the same to the recipients of your email. You must define your style using CSS within
<style >
tags.
The following example changes the font of your email to Courier, adds a border to the table, and changes the color of the table rows:
<messaging:emailTemplate recipientType= "Contact" relatedToType= "Account" subject= "Case report for Account: {!relatedTo.name}" replyTo= "[email protected]" >
<messaging:htmlEmailBody >
<html >
<style type= "text/css" > body {font-family: Courier; size: 12pt;} table { border-width: 5px; border-spacing: 5px; border-style: dashed; border-color: #FF0000;
} background-color: #FFFFFF; td { border-width: 1px; padding: 4px; border-style: solid;
} border-color: #000000; background-color: #FFEECC; th {
204
Integrating Email with Visualforce Using a Custom Stylesheet in a Visualforce Email Template color: #000000; border-width: 1px ; padding: 4px ; border-style: solid ; border-color: #000000; background-color: #FFFFF0;
}
</style >
<body >
<p >Dear {!recipient.name}, </p >
<table border= "0" >
<tr >
<th >Case Number </th > <th >Origin </th >
<th >Creator Email </th > <th >Status </th >
</tr >
<apex:repeat var= "cx" value= "{!relatedTo.Cases}" >
<tr >
<td > <a href =
"https://na1.salesforce.com/{!cx.id}" >{!cx.CaseNumber}
</a > </td >
<td >{!cx.Origin} </td >
<td >{!cx.Contact.email} </td >
<td >{!cx.Status} </td >
</tr >
</apex:repeat >
</table >
</body >
</html >
</messaging:htmlEmailBody >
</messaging:emailTemplate >
205
Integrating Email with Visualforce Using a Custom Stylesheet in a Visualforce Email Template
Example of the Rendered Visualforce Email Template
Defining Visualforce Stylesheets in a Custom Component
Although you cannot reference an external stylesheet in a Visualforce email template, you can place the style definitions within a
a component named
EmailStyle
:
<apex:component access= "global" >
<style type= "text/css" > body {font-family: Courier; size: 12pt;} table { border-width: 5px; border-spacing: 5px; border-style: dashed;
} border-color: #FF0000; background-color: #FFFFFF; td { border-width: 1px; padding: 4px; border-style: solid; border-color: #000000;
} background-color: #FFEECC; th { color: #000000; border-width: 1px ;
206
Integrating Email with Visualforce Adding Attachments padding: 4px ; border-style: solid ; border-color: #000000; background-color: #FFFFF0;
}
</style >
</apex:component >
Then, in the Visualforce email template, you can reference just that component:
<messaging:htmlEmailBody >
<html >
<c:EmailStyle />
<body >
<p >Dear {!recipient.name}, </p >
...
</body >
</html >
</messaging:htmlEmailBody >
Note: Any
<apex:component >
tags used within a Visualforce email template must have an access level of global
.
Adding Attachments
You have the ability to add attachments to your Visualforce email templates. Each attachment must be encapsulated within a single
<messaging:attachment >
component. Code within
<messaging:attachment >
can be a combination of HTML and
Visualforce tags.
The previous example shows how to create a Visualforce email template by iterating through some data and displaying it to an email recipient. This example shows how to modify that markup to display the data as an attachment:
<messaging:emailTemplate recipientType= "Contact" relatedToType= "Account" subject= "Case report for Account: {!relatedTo.name}" replyTo= "[email protected]" >
<messaging:htmlEmailBody >
<html >
<body >
<p >Dear {!recipient.name}, </p >
<p >Attached is a list of cases related to {!relatedTo.name}.
</p >
<center >
<apex:outputLink value= "http://www.salesforce.com" >
For more detailed information login to Salesforce.com
</apex:outputLink >
</center >
</body >
</html >
</messaging:htmlEmailBody >
<messaging:attachment >
<apex:repeat var= "cx" value= "{!relatedTo.Cases}" >
Case Number: {!cx.CaseNumber}
Origin: {!cx.Origin}
207
Integrating Email with Visualforce Adding Attachments
Creator Email: {!cx.Contact.email}
Case Number: {!cx.Status}
</apex:repeat >
</messaging:attachment >
</messaging:emailTemplate >
This markup renders in an email as an attached data file, without any formatting. You can display the data in a more readable format by using one of the following options:
•
•
•
Changing the Filename
The
<messaging:attachment >
tag has an attribute called filename
that defines the name of the attached file. While it is good practice to define an easily identifiable name, it is not required. If you leave it undefined, Salesforce generates a name for you.
A filename without an extension defaults to a text file. You can render an attached file as a CSV:
<messaging:attachment filename= "cases.csv" >
<apex:repeat var= "cx" value= "{!relatedTo.Cases}" >
{!cx.CaseNumber}
{!cx.Origin}
{!cx.Contact.email}
{!cx.Status}
</apex:repeat >
</messaging:attachment >
You can also render the data as an HTML file:
<messaging:attachment filename= "cases.html" >
<html >
<body >
<table border= "0" >
<tr >
<th >Case Number </th > <th >Origin </th >
<th >Creator Email </th > <th >Status </th >
</tr >
<apex:repeat var= "cx" value= "{!relatedTo.Cases}" >
<tr >
<td > <a href =
"https://na1.salesforce.com/{!cx.id}" >{!cx.CaseNumber}
</a > </td >
<td >{!cx.Origin} </td >
<td >{!cx.Contact.email} </td >
<td >{!cx.Status} </td >
</tr >
</apex:repeat >
</table >
</body >
</html >
</messaging:attachment >
208
Integrating Email with Visualforce Adding Attachments
Although you can only define one filename for every
<messaging:attachment >
component, you can attach multiple files to an email.
Changing the
renderAs
Attribute
Similar to other Visualforce pages, setting the renderAs
<messaging:attachment >
component renders the attachment as a PDF. For example:
<messaging:attachment renderAs= "PDF" filename= "cases.pdf" >
<html >
<body >
<p >You can display your {!relatedTo.name} cases as a PDF: </p >
<table border= "0" >
<tr >
<th >Case Number </th > <th >Origin </th >
<th >Creator Email </th > <th >Status </th >
</tr >
<apex:repeat var= "cx" value= "{!relatedTo.Cases}" >
<tr >
<td > <a href =
"https://na1.salesforce.com/{!cx.id}" >{!cx.CaseNumber}
</a > </td >
<td >{!cx.Origin} </td >
<td >{!cx.Contact.email} </td >
<td >{!cx.Status} </td >
</tr >
</apex:repeat >
</table >
</body >
</html >
</messaging:attachment >
Limitations of the Visualforce PDF rendering service include the following.
•
PDF is the only supported rendering service.
•
The PDF rendering service renders PDF version 1.4.
•
Rendering a Visualforce page as a PDF file is intended for pages designed and optimized for print.
•
A Visualforce page rendered as a PDF file displays either in the browser or is downloaded, depending on the browser’s settings.
Specific behavior depends on the browser, version, and user settings, and is outside the control of Visualforce.
•
The PDF rendering service renders the markup and data on your page, but it might not render formatting contained within the contents of rich text area fields added to the page.
•
Long lines of text that don’t have break points, such as a space or dash, can’t be wrapped by the PDF rendering service. This most commonly happens with very long URLs, registry entries, and so on. When these lines are wider than the page, they increase the width of the page’s content beyond the edge of the PDF page. This causes content to “flow” off the side of the page, cutting it off.
•
Don’t use standard components that aren’t easily formatted for print, or form elements such as inputs or buttons, or any component that requires JavaScript to be formatted.
•
PDF rendering doesn’t support JavaScript-rendered content.
•
PDF rendering isn’t supported for pages in Salesforce1.
•
The font used on the page must be available on the Visualforce PDF rendering service. Web fonts aren’t supported.
209
Integrating Email with Visualforce Adding Attachments
•
If the PDF file fails to display all the page’s text, particularly multibyte characters such as Japanese or accented international characters, adjust your CSS to use a font that supports them. For example:
<apex:page showHeader= "false" applyBodyTag= "false" renderAs= "pdf" >
<head >
<style > body { font-family: 'Arial Unicode MS' ; }
</style >
</head >
<body >
これはサンプルページです。
<br/ >
This is a sample page: API version 28.0
</body >
</apex:page >
“Arial Unicode MS” is the only font supported for extended character sets that include multibyte characters.
•
If you use inline CSS styles, set the API version to 28.0 or later. Also set
<apex:page applyBodyTag= "false" >
, and add static, valid
<head >
and
<body >
tags to your page, as in the previous example.
•
The maximum response size when creating a PDF file must be less than 15 MB before being rendered as a PDF file. This limit is the standard limit for all Visualforce requests.
•
The maximum file size for a generated PDF file is 60 MB.
•
The maximum total size of all images included in a generated PDF is 30 MB.
•
PDF rendering doesn’t support images encoded in the data:
URI scheme format.
•
The following components don’t support double-byte fonts when rendered as PDF.
–
<apex:pageBlock >
–
<apex:sectionHeader >
These components aren’t recommended for use in pages rendered as PDF.
•
If an
<apex:dataTable >
or
<apex:pageBlockTable >
has no
<apex:column >
components that are rendered, rendering the page as PDF fails. To work around this issue, set the table component’s rendered
attribute to false
if none of its child
<apex:column >
components are rendered.
Adding Styles and Images
Attachments rendered as PDFs can reference static resources through the
. This enables you to refer to an image or stylesheet within the body of the PDF.
For example, the following attachment includes a logo in the PDF:
<messaging:attachment renderAs= "PDF" filename= "cases.pdf" >
<html >
<body >
<img src = "{!$Resource.logo}" />
...
</body >
</html >
</messaging:attachment >
210
Integrating Email with Visualforce Using Custom Controllers within Visualforce Email Templates
This attachment references a stylesheet you have saved as a static resource:
<messaging:attachment renderAs= "PDF" >
<html >
<link rel= 'stylesheet' type= 'text/css' href= '{!$Resource.EMAILCSS}' />
<body >
...
</body >
</html >
</messaging:attachment >
Warning:
Referencing static resources on a remote server can increase the time it takes to render a PDF attachment. You can’t reference remote resources when creating PDF attachments in an Apex trigger; doing so will result in an exception.
Using Custom Controllers within Visualforce Email Templates
Visualforce email templates can leverage custom controllers to render highly customized content. To do so, include a custom component in a Visualforce email template that uses that custom controller.
For example, suppose you want to display a list of all accounts beginning with the word “Smith” in an email template. To do this, first write a custom controller that uses a SOSL call to return a list of accounts that begin with “Smith”: public class findSmithAccounts { private final List<Account> accounts; public findSmithAccounts() {
} accounts = [select Name from Account where Name LIKE 'Smith_%' ];
} public List<Account> getSmithAccounts() {
} return accounts;
Next, create a custom component named smithAccounts
that uses this controller:
<apex:component controller= "findSmithAccounts" access= "global" >
<apex:dataTable value= "{!SmithAccounts}" var= "s_account" >
<apex:column >
<apex:facet name= "header" >Account Name </apex:facet >
{!s_account.Name}
</apex:column >
</apex:dataTable >
</apex:component >
Tip: Remember that all custom components used in Visualforce email templates must have an access
level of global
.
Finally, create a Visualforce email template that includes the smithAccounts
component:
<messaging:emailTemplate subject= "Embedding Apex Code" recipientType= "Contact" relatedToType= "Opportunity" >
<messaging:htmlEmailBody >
<p >As you requested, here 's a list of all our Smith accounts:</p>
<c:smithAccounts/ >
<p >Hope this helps with the {!relatedToType}.
</p >
211
Integrating Email with Visualforce Using Custom Controllers within Visualforce Email Templates
</messaging:htmlEmailBody >
</messaging:emailTemplate >
Notice that although the relatedToType
attribute is required by the emailTemplate
component, it does not have any effect on this example. It has the value of
"Opportunity"
only to show that it can take an object value that is different than the object used in the custom component.
Note: Sharing settings are enforced if your email templates use a standard controller. If your organization-wide default for the user object is set to Private and you need to access user information such as name and email address in your Visualforce email template, you can use a custom component or custom controller with the without sharing
keywords.
For information about sharing for the user object, see
User Sharing Overview
in the Salesforce online help.
212
Download
Annonce