When accessing templates and needing multiple objects I will
- select the template from the database
- define a merge syntax, use regular expressions "{!([A-z_]+)}" to get a key name
- pass a map<String,String> of data to replace the key (if exists) with data
you now have a template which is just a string. you can push the template to a VF page with <apex:outputText escape="false" value="{!template1}"/>
or send an email manually in code.
code example:
public static Map<String,String> merge_template(Map<String,String> obj, EmailTemplate email){
Map<String,String> data = new Map<String,String>();
String html = email.HtmlValue;
if(html!=null){
html = m(html,obj,Pattern.compile('(\\{![A-Za-z_]+\\})').matcher(html));
data.put('HtmlValue',html);
}
else{
data.put('HtmlValue','');
}
String body = email.Body;
String subject = email.Subject;
body = m(body,obj,Pattern.compile('(\\{![A-Za-z_]+\\})').matcher(body));
data.put('Body',body);
return data;
}
private static String m(String body,Map<String,String> obj,Matcher m){
while(m.find()){
String merge_field = m.group(0);
String field = merge_field.substring(1,merge_field.length()-1);
String value;
try{
value = (String) obj.get(field);
}
catch(Exception e){
value='';
}
if(value!=null){
body = body.replace(merge_field,value);
}
else{
body = body.replace(merge_field,'');
}
}
return body;
}
public static Map<String,String> build(String template,Map<String,String> data){
EmailTemplate et = (EmailTemplate) UtilsList.getFirst([SELECT HtmlValue,Body,Subject FROM EmailTemplate WHERE DeveloperName = :template]);
return merge_template(data,et);
}