Using email template in outbound emails

While sending outbound emails in apex we may need to use an existing email template(text or html or visualforce), in such a case it is mandatory to use target object id i.e lead/contact/user. Now, salesforce uses this object id for getting merge fields values, also it uses the email field from that object to send the mail to.

We may not need to send the email to that email id rather we may  have other email ids. But, in this case it will send the email to the target object email id. And it does not send the email to the mails set  in toAddresses. To avoid this and also make use of the email template we have to somehow get the body of the email template  within   our code. For this, just create a instance of outbound email object, set the email template along with a target object id, but then you have to make sure you roll back this steps so that the mail.

public class SendmyEmail {
 Public SendmyEmail(){
   //Create a dummy instance of outbound email object
   Messaging.SingleEmailMessage message= new Messaging.SingleEmailMessage();
   //set a roolback point
   Savepoint sp = Database.setSavepoint();
  //set desired email template id
   message.templateId = '00e90000560tji7p';
   // set the target object record id(this is mandatory while using email template)
   id recId = [select id from contact limit 1].id;
   message.targetObjectId = recId ;
   //fire dummy email
   messaging.sendEmail(new Messaging.SingleEmailMessage[] { message});
   //roll back to savepoint so that email is not sent
   Database.rollback(sp);
   //Create insatnce of actual email
   Messaging.SingleEmailMessage messageNEW= new Messaging.SingleEmailMessage();
   //get the bode from above dummy instance and set it to your actual email
   messageNEW.HTMLBody = message.getHtmlBody();
   //set desired email addresses
   messageNEW.toAddresses = new String[] { 'johncarly_1990@testmail.com' };
   //send the mail
   messaging.sendEmail(new Messaging.SingleEmailMessage[] { messageNEW});
 }
}

using custom label in visualforce page

A custom label can used to store a desired text value of length up to 1000. A custom label value can then be referenced by apex code or visualforce page. A custom label can store values of length up to 1000 characters in it. We can have a total of 5000 custom labels in an org.
Create a custom label by navigating to set up -> create -> custom label

In the below example let us see how we can access the custom label in visualforce page directly.

Visualforce page that accesses the custom label 

<apex:page controller="custlabelcontroller">
   <apex:form >
     <apex:pageblock >
       Value stored in custom label is: {!$Label.category}
     </apex:pageblock>
   </apex:form>

</apex:page>



call batch apex from trigger

A batch apex can be called from a class as well as from trigger code. But, we have to be very very carefull while calling a batch apex from trigger.

Batch apex

global class BatchApexDemo implements database.batchable<sobject>{
Public string soqlquery;
 Public void setQry(string soqlquery){
    this.soqlquery = 'Select name,status from account limit 1';  
 }
 global database.querylocator start(database.batchableContext bc){
   return database.getquerylocator(soqlquery);
 }
 global void execute(database.batchablecontext bd, list<sObject> sc){
   System.debug('**In Execute Method**');  
 }
 Public void finish(database.batchableContext bc){ 
 }
}


Trigger

trigger callbatchapex on Account (after insert) {
 List<account> accList = new List<account>();
 for(account acc : trigger.new){
     if(acc.annualrevenue < 20000)
        accList.add(acc); 
 }
    if(accList.size() > 0)
      database.executebatch(new BatchApexDemo(),200);
}

calling batch apex from class

Use database.execute method to call a batch apex from a class.

Batch apex class

global class BatchApexDemo implements database.batchable<sobject>{
Public string soqlquery;
 Public void setQry(string soqlquery){
    this.soqlquery = 'Select name,status from account limit 1';
 }
 global database.querylocator start(database.batchableContext bc){
  return database.getquerylocator(soqlquery);
 }
 global void execute(database.batchablecontext bd, list<sObject> sc){
   Account ac = sc[0];
  ac.status = active;
  update ac;
 }
 Public void finish(database.batchableContext bc){
 
 }
}

Class that calls the above batch apex

Public Class callBatchApexclass{
 Public callBatchApexclass(){
   database.executebatch(new BatchApexDemo(),200);
 }
}

Execute the above class from developer console. Set up -> developer console -> debug --> open execute anonymous window -> write your code --> execute

Developer console code
callBatchApexclass cBa = new callBatchApexclass();



using an inline visualforce page

An inline visualforce page is a vf page which can be embedded within a detail page of a record. Salesforce allows doing so, in the edit page layout option. A vf page would be available for embedding in the detail page layout provided page is using standard controller of that particular object. For example, in the below example a inline vf page of standard controller 'contact' would be available for embedding in contact records only.

visualforce page
<apex:page standardController="contact" extensions="inlinecontroller">
 <apex:form >
   <apex:pageBlock title="My Inline Visualforce page">
    Account Name <apex:outputField value="{!accRec.name}"/><br/>
     Account Number  <apex:outputField value="{!accRec.accountnumber}"/><br/>
     Annual Revenue     <apex:outputField value="{!accRec.annualrevenue}"/>
   </apex:pageBlock>
 </apex:form>
</apex:page>

Controller
public with sharing class inlinecontroller {
Public contact conRec{get;set;}
Public id accRecId;
Public account accRec{get;set;}
    public inlinecontroller(ApexPages.StandardController controller) {      
     accRecId = [select id,accountid from contact where id = :ApexPages.currentPage().getParameters().get('id')].accountid;
      if(accRecId != null)
         accRec = [select id,name,accountnumber,annualrevenue from account where id =:accRecId];
    }
}

Related Articles

using custom label in apex code

Custom labels are used to store custom text values which can be accessed in apex code or visualforce pages. It is also possible to translate these custom values in different languages. A custom label can hold up to 1000 characters in it and an org can have a total of 5000 custom labels.
You can Create a custom label by navigating to set up -> create -> custom label

In the below example let us see how we can access the custom label in apex. Let's assume we have created a custom label of name category with a value "A Custom Label Value"


Visualforce page
<apex:page controller="custlabelcontroller">
   <apex:form >
     <apex:pageblock >
       Value stored in custom label is: {!customValue}
     </apex:pageblock>
   </apex:form>
</apex:page>

Controller
Public class custlabelcontroller{
Public string customValue{get;set;}
  Public custlabelcontroller(){
  customValue = Label.category;
  }
}



get all the fields of a object in apex

In order to get all the fields of a object in apex use getdescribe method on Schema.SObjectType as done in the example below. Select the object in the picklist, this would display all the fields for that object.



Visualforce Page
<apex:page controller="AllObjectsinOrg">
 <apex:form >
   <apex:pageBlock id="pgblck">
    <apex:outputlabel value="Object Name" for="ObjPickList"/>           <apex:selectList value="{!ObjectSelected}" multiselect="false" id="ObjPickList" size="1">
       <apex:selectOptions value="{!ObjList}"/>
       <apex:actionSupport event="onchange"  action="{!fieldsofObject}" rerender="pgblck" />  
    </apex:selectList><br/><br/>
     <apex:outputlabel value="Field Name" for="fldPickList" rendered="{!rendflag}"/>
        <apex:selectList value="{!fldselected}" multiselect="false" id="fldPickList" size="1" rendered="{!rendflag}">
            <apex:selectOptions value="{!FieldList}"/>                                 </apex:selectList>
 </apex:pageBlock>
 </apex:form>
</apex:page>

Controller
public class AllObjectsinOrg {
 Public string ObjectSelected{get;set;}
 Public string fldselected{get;set;}
 Public Map<String, Schema.SObjectType> AllObjmap;
 Public Map <String, Schema.SObjectField> fieldMap;
 Public boolean rendflag{get;set;}
 Public AllObjectsinOrg(){
    AllObjmap = New Map<String, Schema.SObjectType>();
    AllObjmap = Schema.getGlobalDescribe();
    System.debug('******All object Names :'+ AllObjmap.keyset());
}
Public List<selectoption> getObjList(){
    List<selectoption> objList = new List<selectoption>();
    for(string s:AllObjmap.keyset()){
        objList.add(new selectoption(s,s));
    }
  return objList;   
 }
 Public List<selectoption> getFieldList(){
    List<selectoption> fldList = new List<selectoption>();
    if(!fieldMap.isEmpty()){
      for(string s:fieldMap.keyset()){
          fldList.add(new selectoption(s,s));
      }
      if(fldList.size()== 0)
         fldList.add(new selectoption('--None--','--None--'));
    }  
  return fldList;   
 }
  Public void fieldsofObject(){
    fieldMap = New Map <String, Schema.SObjectField>(); 
    fieldMap = AllObjmap.get(objectSelected).getDescribe().fields.getMap();
    System.debug('###### all fields of object## :' + fieldMap.keyset());
    rendflag = true;
 }
}

Wild card search in soql

Use like operator along with % character in where clause of SOQL to implement wild card search. In the following example query returns account records matching input text with account name. %'input string'% in where clause returns all the accounts having the input string anywhere in the account name. For ex.if the input string is 'tech' , query will return account with names 'Willsinfotech' and also 'infotech solutions'

Visualforce
<apex:page controller="wildcardController">
  <apex:form >
    <apex:pageblock >
        <apex:inputtext value="{!inputtext}"/>
        <apex:commandbutton value=" Search " action="{!searchRecords}"/>
    </apex:pageblock>
    <apex:pageblock rendered="{!flagshow}">
      <apex:pageblocktable value="{!accList}" var="acc">
        <apex:column value="{!acc.name}"/>
        <apex:column value="{!acc.accountnumber}"/>
      </apex:pageblocktable>
    </apex:pageblock>
  </apex:form>
</apex:page>

Controller
Public class wildcardController {
    Public string inputtext{get;set;}
    Public List<account> accList{get;set;}
    Public boolean flagshow{get;set;}
    Public wildcardController(){
    flagshow = false;
    }    
    Public void searchRecords(){
    flagshow = true;
      accList = database.Query('select name,accountnumber from account where name like '+'\''+'%'+inputtext+'%'+'\'');
    }
}

using multiple values of multiselect picklist field in soql

An example to demonstrate how we can retrieve records with multiple values in multiselect picklist field. Have used a custom multiselect picklist on account Reason__c with values(Reasons 1, Reason 2, Reason 3, Reason 4)
In order to retrieve records with multiple values for multiselect field we have to use include/Exclude separate the values by semicolon. For example where include(Reason 1;Reason 2) would return records having both of these two values.



Visualforce page
<apex:page controller="MultiselectController">
  <apex:form >
    <apex:pageblock >
    Accounts having Reasons as 'Reason 1' and 'Reason 2'
      <apex:pageblocktable value="{!accList1}" var="acc1">
        <apex:column value="{!acc1.Name}"/>
        <apex:column value="{!acc1.Reasons__c}"/>
      </apex:pageblocktable> 
      </apex:pageblock>
      <apex:pageblock >       
      Accounts having Reasons as both 'Reason 1' and 'Reason 2' OR only 'Reason 2'
      <apex:pageblocktable value="{!accList2}" var="acc2">
        <apex:column value="{!acc2.Name}"/>
        <apex:column value="{!acc2.Reasons__c}"/>
      </apex:pageblocktable>    
    </apex:pageblock>
  </apex:form>
</apex:page>

Controller
Public class MultiselectController {
    Public List<account> accList1{get;set;}
    Public List<account> accList2{get;set;}
    Public MultiselectController(){
        accList1 = New List<account>();
        accList2 = New List<account>();
        accList1 = [select name,reasons__c from account where reasons__C includes('Reason 1;Reason 2')];
        accList2 = [select name,reasons__c from account where reasons__C includes('Reason 1;Reason 2','Reason 2')];
    }
}

get all objects in salesforce org

In order to get all the object names in your org, use Schema.getGlobalDescribe() method. This would return a map of object names and object types. Keyset would be all the object names. Following visualforce page uses this method to display all the objects in an org.


Visualforce page
<apex:page controller="AllObjectsinOrg">
 <apex:form >
   <apex:pageBlock id="pgblck">
    <apex:outputlabel value="Object Name" for="ObjPickList"/>      
    <apex:selectList value="{!ObjectSelected}" multiselect="false" id="ObjPickList" size="1">
       <apex:selectOptions value="{!ObjList}"/>
    </apex:selectList>
 </apex:pageBlock>
 </apex:form>
</apex:page>

Controller
public class AllObjectsinOrg {
 Public string ObjectSelected{get;set;}
 Public Map<String, Schema.SObjectType> AllObjmap;
 Public AllObjectsinOrg(){
    AllObjmap = New Map<String, Schema.SObjectType>();
    AllObjmap = Schema.getGlobalDescribe();
    System.debug('******All object Names :'+ AllObjmap.keyset());
}
Public List<selectoption> getObjList(){
    List<selectoption> objList = new List<selectoption>();
    for(string s:AllObjmap.keyset()){
        objList.add(new selectoption(s,s));
    }
  return objList;   
 }
}

Using offset in soql

We can Use OFFSET keyword in SOQL to specify the starting row from the result  returned by your query. This is useful in cases where we need to quickly jump to a particular subset of the total result returned by SOQL query. For example if there are 20 records then, if we specify offset as 10 in the query then it would return record 11 through 20. In the following example org has total 10 account records (This are displayed in first table) and in the second table query is with offset 7, thus it return accounts 8 through 10 i.e only 3 records.


Visualforce Page
<apex:page controller="OffsetController">
  <apex:form >
    <apex:pageblock >
    Random 5 account records
      <apex:pageblocktable value="{!accAllList}" var="accAll">
        <apex:column value="{!accAll.name}"/>
        <apex:column value="{!accAll.accountnumber}"/>
      </apex:pageblocktable>
    </apex:pageblock>
    <apex:pageblock >
    With Offset as  3,account records
      <apex:pageblocktable value="{!accOffsetList}" var="accOffset">
        <apex:column value="{!accOffset.name}"/>
        <apex:column value="{!accOffset.accountnumber}"/>
      </apex:pageblocktable>
    </apex:pageblock>
  </apex:form>
</apex:page>

Controller
public class OffsetController {
    Public List<account> accAllList{get;set;}
    Public List<account> accOffsetList{get;set;}
    Public OffsetController(){
        accAllList = new List<account>();
        accOffsetList = new List<account>();
        accAllList = [select name,accountnumber from account ];
        accOffsetList = [select name,accountnumber from account OFFSET 7 ];
    }
}

OFFSET keyword can be used to implement pagination in visaulforce page tables.

using custom controllers in visualforce email templates

To be able to do some calculation or query some records to show on a visualforce email template we would certainly need a controller associated with VF email template. But a visualforce email template attribute [<messaging:emailTemplate>] does not allow direct association of controller with it. A workaround for this is, embedding a visualforce component that can use  controller with it. We can then use this component in the visualforce email template. 

Lets say, we want to display some randomly chosen accounts in the email template.This is not possible unless we query in the database to retrieve the records, hence we would use visualforce component to do the task.
For this, we would need to create a visualforce component,its controller and then use the component in the email template as below,

Controller for Visualforce Component
Public class accountList{
Public List accList{get;set;}
 Public accountList(){
  accList = new List([select name,id,description,accountnumber,annualrevenue from account limit 5]);
 }
}
Visualforce Component

  
    
      Name
         
         
           Account Number
             
    
      Annual Revenue
        
    

Visualforce Email template

   
     Congratulations!
     This is your new Visualforce Email Template. Following are a list of randomly choosen accounts in my org:
    
    
   

Now when we use this email template it will populate the records from the visualforce component, as you can see in the screen shot below,
Some points that needs to be considered before using a visualforce component in VisualForce email template:
1. Make sure you specify the access as global for your compoennt, otherwise your email template would not compile and give below error, <messaging:emailTemplate> can only contain components with an access level of global. <c:accountlist> is not valid.
   <apex:component controller="AccountList" access="global">
2. Visualforce email template cannot contain pageblock and its child attributes(pageblocktable for example), also form cannot be included in vf email template, hence you cannot put this in the visualforce compoennt to be used in vf email template, for vf component would be a part of email template itself.

Related Posts

Dynamic attachment in email template

In salesforce email templates, we can send attachments which are predefined or in the salesforce standard Send email UI we can chose the attachment from computer files.
For static/fixed pre defined attachment in email template we can simply add the attachment in the related list of the email template.



This will always send the same attachment that has been configured. We can even send dynamic attachment in case of visualforce email templates, we can code the attachment as we wish to make it dynamic(The attachment content will be dynamic). Say you want to put some content in the attachment which draws record field values.

create a visualforce email template, then edit its contents.As an example following is the default vf email template code that you would see when you edit the template-

<messaging:emailTemplate subject="Product Enquiry" recipientType="Lead" >
  <messaging:plainTextEmailBody >
    Congratulations!
    This is your new Visualforce Email Template.
  </messaging:plainTextEmailBody>
</messaging:emailTemplate>

Now to add attachment dynamically, use <messaging:attachment> attribute, you can render the attachment as wished, the default format is .txt

<messaging:emailTemplate subject="Product Enquiry" recipientType="Lead" >
  <messaging:plainTextEmailBody >
    Congratulations!
    This is your new Visualforce Email Template.
  </messaging:plainTextEmailBody>
  <messaging:attachment filename="yourCases.txt">
     test document in vf page attachment
  </messaging:attachment>
</messaging:emailTemplate>

This would give you a visualforce attachment as related list to the email template


Thus whenever this email template would be used, the visualforce attachment would be send along with the email template.


Inbound email services in salesforce

Lets see how we can use them and demo an example for same. We can receive a email in salesforce and use the information contained in that email i.e access that information in apex and act accordingly on that information.

Lets define a problem and work on it.
Requirement: Create a account record, record should be automatically created when a user sends an email(email will contain all the fields information)

Step 1: create a global class that can receive that email as below

global class InbEmailHandlerClass implements Messaging.InboundEmailHandler {
 global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
        Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
        String emailBody = EncodingUtil.urldecode(email.plaintextbody,'utf-8');
       string[] emaildata = emailbody.split(',');
       Account cobj = new Account();
       cobj.name= emaildata[0];
       cobj.Accountnumber = emaildata[1];
       cobj.Industry = emaildata[2];
       
       insert cobj;
       result.success = true;
       return result;
    }
}

Step 2: You need email address to receive the email. Go to set up -> develop -> email services -> new email services.
 In new email services fill following fields
 1. name: any name you wish
 2. apex class: above class that you created
 3. Active: checked
 4.Click save.
 5. On detail email services record related list create new email address.Fill in the accept from email addresses as per your wish.
    This will be your email address to which the emails should be sent.

Step 3. Send an email from your chosen address to your salesforce email address you saved in step 2
      email format: Remember as per our class you should send field values coma separated and in proper order. That is as an example;
      Email body: testaccountname,1234,Banking
Once a email is sent, your account record would be created(If there are no other validations)

passing parameters in action function

We can pass parameters to controller method that is being called using action function. For this we can use attribute "param" in visualforce.

Following is an example to demonstrate the parameter passing using param in action function. Clicking the checkbox calls the controller method using action function, first name and last name are passed to the controller using param attribute.


Visualforce Page

<apex:page controller="passparam">
 <apex:form>
  <apex:pageblock id="pgblck">
   First name : <apex:inputtext id="fn" value="{!firstname}">
   Last Name :<apex:inputtext id="ln" value="{!lastname}"> 

 Click this to See full name :  <apex:inputcheckbox onclick="calculate('{!$Component.fn}','{!$Component.ln}')">

Full Name:    <apex:outputtext value="{!fullname}"></apex:outputtext> 
  </apex:inputcheckbox></apex:inputtext></apex:inputtext></apex:pageblock>
<apex:actionfunction action="{!calpercentage}" name="calAF" rerender="pgblck">
<apex:param assignto="{!firstname}" name="param1" value="">
<apex:param assignto="{!lastname}" name="param" value="">
</apex:param></apex:param></apex:actionfunction>
 </apex:form>
 <script>
  function calculate(frst,lst){
  var Fname = document.getElementById(frst).value;
 var Lname = document.getElementById(lst).value;
   var res = confirm('Do you want to calculate?');
   if(res == true)
      calAF(Fname,Lname );
  }
 </script>
</apex:page>

Apex Class

Public class passparam{
Public string firstname{get;set;}
Public string lastname{get;set;}
Public string fullname{get;set;}
 Public void calpercentage(){
  fullname = firstname +' '+lastname;
 }

select all checkbox in visualforce using action function

Here is an example that demonstrates select all checkbox column using action function. Though the response is slower, at times we may need to use this depending on requirement.

Visualforce Page ]]> Apex Class

Batch apex scheduling in apex - batch apex job run for every 15 minutes or 30 minutes

We can schedule a batch apex using declarative way/OOTB, for this we need to write the schedule class that calls the batch apex class. Using declarative way we can schedule the class either weekly or monthly basis.

In weekly, we can have it run every day or any selected day of week. For a particular day we can specify a preferred time at which the class run. So, using declarative way we can have a highest frequency of 1 time per day not more than that. That is it does not support to run the class more number of times per day. Say, you want the class to run every 1 hour, or every 30 mins, then you cannot do it using declarative way. To do this, we can use system.schedule method and call the scheduler class. 

System.schedule takes 3 parameters as below :

system.schedule('jobname',timeperiod,scheduler class name)

jobname: you can give any name to your job
timeperiod: specify the time frequency with which the job should run
scheduler class name: scheduler class that calls your batch apex class.

timeperiod should be specified in below format:
Seconds Minutes Hours Day_of_month Month Day_of_week optional_year

For example, to run every 30 mins the expression would be : 0 30 * * * ?

here '*' means every time against the specified parameter, every hour, every day of month, every day of week and '?' means no specific value. Thus, this expression means every 30 minutes. So, the system.schedule('testname',0 30 * * * ?,schedulerclass()); would call the schedulerclass every 30 minutes when the statement executes.

You can visit salesforce documentation to know more on system.schedule parameters.

Lets write a simple batch apex class, its scheduler class and then, execute system.schedule method to run that batch apex every 30 minutes.

Batch Apex Class:
Scheduler class along with method that will Can scheduler class every 30 minutes:
Now, we have to just execute the "SchedulerMethod" once, this will keep on calling the batch apex every 30 minutes. We can use developer console to execute this method. Just execute below statement to call the method: ScheduleBatchApexDemo.SchedulerMethod();

You can monitor the batch apex being called every 30 minutes from: set up--> monitoring jobs

Importing selected salesforce org components in IDE or Eclipse swiftly

IDE/Ecipse is a preferred tool that we all use for coding purpose, when the codes are of short length we prefer UI for coding but when we have very lengthy codes IDE/Eclipse is a best option. It also allows us to search in the entire ORG if any object or field is being referenced in any class, trigger or workflow etc(This is something which is very difficult to do manually from UI in the org).

Many times we require only certain components of the org in IDE/Eclipse, and its only fair to get those components rather then all the components of the org. At times entire org could be so huge that its almost impossible to get the entire org in time. IDE allows us to get the selected components from the org. A faster way to get only selected components is by modifying the package.xml. Here we have to just put the component members (that we wish) in the package.xml file and save it, components will get downloaded very swiftly in this way.

Follow this steps to get only selected components in IDE:

1. Create new project in IDE, fill in all the details (username,password, security token) and click finish.

2. From the "choose initial components" window choose 'none' and click finish, this will instantly create the project.
    

3. Right click on project and select workoffline
 

4. Now open the package.xml file, modify its content to include whichever components you wish to download in IDE


With none components selected your package.xml will look like following:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    
    <version>28.0</version>
</Package>

Now suppose you wish to include trigger,classes and page members then you need to include those members as below

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
    <members>*</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexPage</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexTrigger</name>
    </types>
 <version>28.0</version>
</Package>

4. Press cntrl+s to save the package.xml file

5. Right click on project and select work online, your new components will now be populated in your project. If it does not populate the components, try to refresh from server, or close the IDE and reopen and then refresh from server.