Emails in Cases in Lightning

I don’t think I’ve come across any part of Salesforce that is so hard to understand, set up, manage and build a great user experience.

I may actually give up before I get very far with it. YEP, I GAVE UP. Wait! I’m back, and I think I’ve conquered it! But no, there are STILL issues!

I did a Video a few months ago for regular emails https://www.youtube.com/watch?v=nhhoGRyBnxU and an video on Emails in Cases before that https://www.youtube.com/watch?v=AKQruEHMZ5I to try to surface some of the issues. Now I’m trying to get it set up for real.

Video

00:00 - Intro - Expanding on my video 1 year ago

00:40 - The only answer is code

01:33 - Quick Action Overrides don't work

02:05 - Simple version of the code

02:34 - Understanding the requirements

04:53 - A decision tree document

07:42 - A review of Case setup in Lightning

12:04 - Email Buttons

15:23 - Quick Text

16:36 - Email Preview Issues

17:30 - Files on Cases

18:08 - Email to Client Button

21:16 - Email History and Activity issues

22:19 - Enhanced Email Lightning Page

22:49 - Third Party Email Button

23:40 - Rogue Email Addresses

24:41 - Third Party Email Button

26:17 - Some thread concerns

28:23 - Using the standard buttons on the Email

30:02 - Buttons, buttons everywhere

31:44 - Let's look at the code

35:45 - Validated From Address

36:30 - Setting up Email-to-Case

37:07 - Setting the Email Templates and Subject

38:27 - Get the right Email Template

39:57 - Setting the To Address

43:41 - No HTML Body

44:32 - One extra step to set up the code

45:34 - Weirdness with Templates

47:35 - Despair?

General Email Functionality in Cases

Email Issues

  • If an email comes into the Case, you may have an alert set to notify the Case Owner, but it does not show up in the Feed until you refresh the whole Case.

  • You can’t use Case Merge fields in Lightning Email Templates unless you just type them in when you are in Email Templates. But if you create the Template from the Case itself, then you can insert Merge Fields from Cases. Bizarre.

  • The Email History in the Activity component goes to Tasks, not to Enhanced Email! Why? Bizarre!

  • The Cases object is font-a-palooza. There are so many fonts on the page, in the email, in the feed and in the enhanced email it just makes it look completely ugly.

  • The complete and utter bizarre ugliness that you can have visible on the screen if you reply to an email from the Enhanced Email popup plus the feed is just ludicrous.

  • Inserting an Email Template with a Letterhead allows the letterhead to be edited (See this NO FIX KI)

Interesting Things

  • Handlebars merge format works in Custom Email Templates

  • Classic Merge Format works in Quick Text used in Lightning Emails.

  • Quick Text is good. Just use Quick Text.

  • Validated From is an Email Address and is either

    • Org Wide Default Email address

    • Email-to-Case Email address - but see Email To Case as to why you don’t want to use that.

    • The User Email

  • To can be an ID or an Email Address.

The Salesforce Way

So basically what Salesforce is saying in the way they have set up Cases, is that when handling cases you only ever going to have a very simple case with a couple of fields on it and you only ever going to email the person who submitted the Case back and forth until the case of resolved and the Case can be closed.

If you have any other Case functionality other than that, then don’t bother trying to set up Cases with configuration only, you are going to need to do a heap of work to try to overcome what Salesforce thinks is the only way to handle Cases.

In my case the functionality I need is

  • A heap of custom fields - where the fields change through the course of the Case process - this is currently handled by Record Types and Page Layouts, but one day in many years time it may be able to be handled by https://tddprojects.atlassian.net/wiki/spaces/SF/pages/965312517.

  • Emails that MUST only come from the Org Wide Email Address and the Case Owner or User’s Name must never be on the Email.

  • Emails go to the client (Case Contact) OR to a third party. AND we must never cross the streams, so the way Salesforce insists that the email thread is maintained and you will always just reply to the same email is NEVER going to work.

Email Button / Send Email Quick Actions

  • You have to create an Email button yourself the standard Email action just does not work in Cases. See Help Article.

  • Even following the help article, the Email button on its own will NOT override the From or the To or the Subject. Cases thinks it knows best and just does what it thinks is best. This is NOT best.

  • Use the JUNCTIONIDLIST formula to try to set the TO in the Email Quick Action. Eg JUNCTIONIDLIST(Case.ContactId)

  • You can only use Custom Email Templates, not even VF Email Templates or Lightning Email Templates as the default Email Template from the Button, but if you use Code, you can use Lightning Email Templates at least!

  • When you create Email Quick Actions and add them to the Case Feed, they also get added to two places on the Case Feed that is completely inappropriate!

    • The only way around this would be to have some way of making the code work for ALL scenarios from the one button. And I just can’t work out a way that can work.

    • OMG this is by DESIGN! (or at least it is documented that this will happen! UNBELIEVABLE! From the Help Doc “For each email in the case feed, agents see a dropdown menu with reply options. If you have multiple email actions in the case feed publisher, agents see groups of reply actions in the dropdown menu”. So they actually do NOT want you to EVER send a brand new email, they are only ever Replys? Sure, but then why do the Reply Actions appear in the Forward menu? Stupid. Stupid Stupid.

Using Code to Send Emails

My Decision Tree

Name

When

Button Name

From Address

To Address

Signature

Template

Subject

Include Body

REF Included

Attachments

To Client

Any time

Email to Client

test@example.com

Primary Contact.Email

Sender.Title

BLANK

Your Case - {subject} {EmailThreadId}

No

Yes

Add any required

Reply to existing email

Any time

Reply or Reply All from Email

test@example.com

From Address

Sender.Title

BLANK

Re: Existing Subject

Yes

Yes

No

 

 

Reply

test@example.com

From Address

Sender.Title

BLANK

Re: Existing Subject

Yes

Yes

No

Forward an existing email

Any time

Forward from Email

test@example.com

Enter a valid address

Sender.Title

BLANK

FW: Existing Subject

Yes

Yes

Included

To Third Party

Any time

Third Party Email

test@example.com

ThirdParty.Email

Sender.Title

THIRD PARTY BLANK

Case for {ClientName} - {Subject} {EmailThreadId}

No

Yes

Add any required

Code Gotchas

  • Make sure you set the setting “Enable Default Email Templates or the Default Handler for Email Action” in Support Settings and choose the Apex Class there.

  • When inserting Email Templates via Code, they can NOT include Attachments, but you can use the public link to the File in a Hyperlink on the Email, and that is a better way to send attachments anyway.

  • The ID of the Email Template for Lightning Email Templates is just the ID in the URL, but if you want to use the Developer Name you will have to use SOQL or Salesforce Inspector to see the Developer Name.

  • When you do code, ensure you cater for the standard Reply, Reply All and Forward scenarios on the Enhanced Email also.

My Code

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 global class EmailDefaults implements QuickAction.QuickActionDefaultsHandler { global void onInitDefaults(QuickAction.QuickActionDefaults[] defaultsList) { for (Integer i = 0; i < defaultsList.size(); i++) { QuickAction.QuickActionDefaults defaults = defaultsList.get(i); // Check if the quick action is the standard case feed `SendEmail` action if ( defaults instanceof QuickAction.SendEmailQuickActionDefaults && defaults.getTargetSObject().getSObjectType() == EmailMessage.sObjectType && defaults.getActionType().equals('SendEmail') ) { String actionName = defaults.getActionName(); Id contextId = defaults.getContextId(); // check if the related object is a Case // and process it in the same way no matter if it's // a `SendEmail`, `Reply`, or `Reply All` action if ( (actionName.equals('Case.Send_Email') || actionName.equals('Case.ReplyEmail') || actionName.equals('Case.ThirdPartyEmail') || actionName.equals('EmailMessage._Reply') || actionName.equals('EmailMessage._Forward') || actionName.equals('EmailMessage._ReplyAll')) && contextId != null && contextId.getSobjectType() == Case.sObjectType ) { applySendEmailDefaultsForCase((QuickAction.SendEmailQuickActionDefaults) defaults, actionName); break; } } } } private void applySendEmailDefaultsForCase(QuickAction.SendEmailQuickActionDefaults sendEmailDefaults, string sendType) { Case c = [ SELECT ContactId, LinkedContID__c, ThirdParty__c FROM Case WHERE Id = :sendEmailDefaults.getContextId() ]; EmailMessage emailMessage = (EmailMessage) sendEmailDefaults.getTargetSObject(); if (sendType.contains('Reply')) { sendEmailDefaults.setTemplateId(getTemplateId('developerName')); sendEmailDefaults.setInsertTemplateBody(true); sendEmailDefaults.setIgnoreTemplateSubject(true); emailMessage.ValidatedFromAddress = 'orgwidemail@example.com'; } else if (sendType.contains('Forward')) { sendEmailDefaults.setTemplateId(getTemplateId('developerName')); sendEmailDefaults.setInsertTemplateBody(true); sendEmailDefaults.setIgnoreTemplateSubject(true); emailMessage.ValidatedFromAddress = 'orgwidemail@example.com'; } else if (sendType.contains('ThirdParty')) { String[] toIdsThirdParty = new String[]{c.ThirdParty__c}; sendEmailDefaults.setTemplateId(getTemplateId('developerName')); sendEmailDefaults.setInsertTemplateBody(true); sendEmailDefaults.setIgnoreTemplateSubject(false); emailMessage.ToIds = toIdsThirdParty; emailMessage.ToAddress = ''; emailMessage.ValidatedFromAddress = 'orgwidemail@example.com'; emailMessage.HTMLBody = ''; } else{ //This is the default. New Email to Case Contacts only. String[] toIds = new String[]{c.ContactId, c.LinkedContID__c}; sendEmailDefaults.setTemplateId(getTemplateId('developerName')); sendEmailDefaults.setInsertTemplateBody(true); sendEmailDefaults.setIgnoreTemplateSubject(false); emailMessage.ToIds = toIds; emailMessage.ToAddress = ''; emailMessage.ValidatedFromAddress = 'orgwidemail@example.com'; emailMessage.HTMLBody = ''; } } private ID getTemplateId( String templateName ) { ID templateId = null; List<EmailTemplate> templates = new List<EmailTemplate>([ SELECT id FROM EmailTemplate WHERE developerName = :templateName LIMIT 1 ]); if ( templates.size() > 0 ) { templateId = templates[0].id; } else { System.debug( LoggingLevel.ERROR, 'Unable to locate email template using name "' + templateName + '"' ); } return templateId; } }

A Fix

I fixed it! I had to simplify my requirements a bit, and it’s the best of a really bad situation.

  • I changed the button name to Email

  • If the Case is at Status - “Ready for Service” then the “ThirdParty” code above will be used.

I changed

else if (sendType.contains('ThirdParty')) {

else if (c.Status.contains('Service')) {

and added Status to the SOQL query

  • If the Case is at any other Status then the default Email to Client Code will be used.

  • If they want to Reply to an Email they choose the email in the list and click Reply. AND there is only ONE REPLY BUTTON now!!!!

  • If they want to do something out of the ordinary then they need to carefully change the email to be what they want - change the To, the Subject, and insert a new Template.

OMG that took so much work and took so long to work through.

Bottom Line - NEVER USE MORE THAN ONE Email Button on Cases! EVER!

Testing This Code

I am SOO stuck on testing this code.

This is the extent of the Code Coverage I am getting following many of the examples of test classes found on Github. THIS SHOULD NOT BE THIS HARD. I am trying to install this solution in an org that has only this code and I can not get anywhere near the 75% code coverage.

The "suggested" way to test is https://salesforce.stackexchange.com/questions/102338/test-class-for-quickaction-quickactiondefaultshandler
My test Class currently creates a Closed Case and does a Reply Email and the code coverage is not even looking at the Status of the Case let alone hitting the bit of code that actually sets the default templates.