With the option 'Enable Email Approval Response' checked, you can approve to text email by replying 'Yes','No', 'APPROVE', 'REJECT',etc.
Is possible to reply your approval or rejection on an email that has an html email template?
Thanks,
Nawshine
With the option 'Enable Email Approval Response' checked, you can approve to text email by replying 'Yes','No', 'APPROVE', 'REJECT',etc.
Is possible to reply your approval or rejection on an email that has an html email template?
Thanks,
Nawshine
It seems that my suspicions, Brad B and the docs are right, you cannot alter the default notification template. It has to be overridden. Therefore the solution to the question I posed (for those who come across this) is as follows.
First, I'd recommend you make the logo you want to include a public document in your salesforce org. This is best approached by clicking the "Documents" tab (which may be hidden under the tab + sign).
From there upload your logo file, to the Shared Documents folder, making it an Externally Available Image
..then select and upload your file.
Putting this logo at the top of an e-mail can be done by creating a rich letterheaded e-mail, so click through Setup > Communication Templates > Letterheads click "New Letterhead" give it a name and label, make it "Available for use" and click to Save. In the letterhead editor, click "Select Logo" and then find your document in the popup.
Save your letterhead.
Now navigate to e-mail templates, Setup > Communication Templates > Email Templates and click to create a new one. Select "HTML (using Letterhead)" and click next,
Fill in your folder, template name and pick your letterhead from the dropdown. Choose freeform letter (for the best approval process looking email) make sure it is available for use and "Next".
Now you can set a subject and body as follows: (to mimic default behaviour) )
With "Approval by email reply" enabled :
For the subject use Salesforce record awaiting approval
For the body:
{!User.FirstName} {!User.LastName} has requested your approval for
the following item.
To approve or reject this item, reply to this email with
the word APPROVE, APPROVED, YES, REJECT, REJECTED, or NO
in the first line of the email message, or click this link:
{!ApprovalRequest.External_URL}
If replying via email you can also add comments on the
second line. The comments will be stored with the approval
request in Salesforce CRM.
Note: For salesforce.com to process your response the word
APPROVE, APPROVED, YES, REJECT, REJECTED, or NO must be in
the very first line of the reply email. Also, any comment
must be in the second line.
If you do not have the approve by e-mail feature on, use:
Subject: Approval Request
Body
{!User.FirstName} {!User.LastName} has requested your approval for the following item: {!ApprovalRequest.External_URL}
Please click this link to approve or reject this record.
Thank you,
salesforce.com
Paste the same text into the plain text body field too, this means if users mail clients don't support rich content, they still get the message body.
Then, you have your duplicate e-mail template set up, but with a logo.
To assign this to an approval process, through the browser navigate to the approval process in question and click on the "Edit" downarrow at the top, and choose notification template:
On this page, you can select your e-mail template (using the lookup dialogue) and, once saved, next time the record approval e-mail is dispatched, it will have a logo on it!!
(regarding updating all Approval processes to use this new template en masse, I can't advise right now. You will have to update each one through the browser).
Welcome to SF.SE Ankush. What the custom email service is primarily going to allow you to do is to send all of the emails at once to everyone in the queue, then when the first one is returned, it can determine if it was approved or rejected using custom code. Is that what you want to do? This would be more like a running a class where emails are returned to an inbound email service that processes them. The first reply is the only one that's needed to approve or reject the request and ends the process for that request.
I believe this basic functionality already exists without needing to recreate the wheel. You can create an approval process where only one in the list of approvers is needed to approve or reject. While you don't assign it to a queue per se, you do assign the approval process to those who can approval or reject either by role or as supervisors, user, etc. With this being the case, I'd highly recommend you see if you can recreate the list of users that would be in your queue using this type of built-in functionality in SF first, before trying to create a queue using Apex code running from a class.
Otherwise, it would almost appear as though you'd need to assign the approval to an API user when you did this to send to your class; something I'm not entirely certain SF will allow you to do (I've not attempted to do this before). With that as input to your class, you'd need to process emails to everyone in the queue. I'd recommend using a list stored in custom settings or that can be easily retrieved by running a query on the members of your queue.
When your emails are returned, you'd then process the approval reply back as a response by the API user based on the 1st email response from those who are in the queue. Any further email responses could simply be ignored or responded to as "already processed" according to logic you'd create in your inbound email handler. That would be the general approach to coding this with a custom email service where all replies are handled according to whatever logic you chose to set up in the inbound service.
There are numerous examples of inbound email services available to you is you use the search function here on SF.SE. I believe you'll also find code for using one along with directions for setting it up in the Apex API. Here's a link to Using Apex for Approval Processing which includes an Example.
I have some better example code I could share, but can't seem to locate it at the moment. I'm confident you'll find some better examples by using the search box here on the site.
I found the code I had which uses custom settings to store an email address. You could store a list of addresses if you wanted and pass it to an array, which is not what this class does. You can also code it to process inbound emails. I can't seem to find the code example that I had from Jeff Douglass and Wes Nolte's book. You might find it on Jeff's Blog.
// This class was used to send a custom alert message when a trigger encountered various data related
// errors that it had trapped. It assembled the message in the body, then sent it via the class to the
// primary admins in the org so they could take appropriate actions to correct the problems with the data
global class InboundEmail_Automation_Error_Handler implements Messaging.InboundEmailHandler {
global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.InboundEnvelope envelope) {
Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();
// here's where you'd want to add your code to process inbound email replies to your
// approval request and call a method to reply if you'd already received a response
// what's below would become part of a method for sending the outbound messages with the
// approval request and for sending the reply if you'd received a response
Messaging.SingleEmailMessage outbound = new Messaging.SingleEmailMessage();
outbound.ToAddresses = new String[] { email.replyto };
outbound.setSenderDisplayName('Apex Automation Error Handler');
outbound.setSubject('Re: ' + email.subject);
outbound.setHTMLBody('<p> This is an auto-generated Apex reply message.' + 'You wrote: </p><i>'+ email.plainTextBody +'</i>');
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {outbound });
return result;
}
global static void send_Error_Emails (String trigname, map<Id,String>mssgmap) {
PrimAdmin_CustSttng__c Admin1 = PrimAdmin_CustSttng__c.getValues('PrimAdmin1');
PrimAdmin_CustSttng__c Admin2 = PrimAdmin_CustSttng__c.getValues('PrimAdmin2');
set<Id>Idset = new set<Id>();
string subject;
Idset = mssgmap.keyset();
if(trigname == 'SendRecapLinksTrigger' || trigname == 'RecapRollupToOppTrigger'){
subject = 'Automation Errors Handled by trigger '+ trigname +' on RecapForm Id: ';
}else if(trigname == 'CreateAssignmentsTrigger'){
subject = 'Automation Errors Handled by trigger '+ trigname +' on Event Id: ';
}else if(trigname == 'FATAL_TRIGGER_ERROR'){
subject = 'FATAL AUTOMATION ERROR HANDLED: '+ trigname +' on Id: ';
}else {
subject = 'Automation Errors Handled by trigger '+ trigname +' on Opp Id: ';
}
string body2;
string body = ' ';
string subject2;
for(Id Iss: Idset){
subject2 = subject + Iss + ', '; // Id
body2 = body + mssgmap.get(Iss) +'. \n' ;
subject = subject2;
body = body2;
}
system.debug('subject = '+ subject );
system.debug('body = '+ body );
Messaging.SingleEmailMessage outbound = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {string.valueOf(Admin2.Email__c) };
string[] ccAddresses = new string[] {string.valueOf(Admin1.Email__c)};
outbound.setSenderDisplayName('Apex Automation Error Handler');
outbound.setToAddresses(toAddresses);
outbound.setCcAddresses(ccAddresses);
outbound.setSubject(subject);
outbound.setUseSignature(false);
outbound.setPlainTextBody(body);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {outbound });
}
}
Best Answer
Yes you can. It allows using Letter head email templates, even if it is not specified in the documentation.