Send Rich Email

UPDATE 11-24-19

A new version (1.1) is available below. The attachment mechanism has been changed. The action now accepts a collection of Content Document Links, which are basically references to files that you’ve added to a record. If you’re working from a record, it’s easy to attach the documents that are part of it. If you need a general-purpose attachment mechanism, I suggest you create a special record on a custom object to serve as your defacto file store. You can add files to that store with the standard Flow File Upload component by passing the recordId into the component, and you can use a Get Records on Content Document Links (as shown in the video) to select the attachments you want to add.

If you want to pull an email address from an Email field, you can’t pass it directly to input attributes like SendTOThisOneAddress, but you can use this action to first convert the email into a simple text string.

Video introduction

Installation (See bottom of post)

Source code

Flow provides a built-in Send Email action but it’s something of an underachiever. However, using the power of Apex and Flow Actions, its possible to build a powerful SendHTMLEmail action that can be easily installed and used from within Flow Builder. MVP Jeremiah Dohn pioneered this space several years back with his well received HTML Email Flow action. The version here is similar and adds a couple of additional capabilities.

This improved email experience provides:

Rich, HTML email bodies that can use all of the capabilities of Flow’s Text Templates, including Bold, Italics, Underline, Bullets and Numbers, Left/Center/Right justification, URLs, images, fonts, and text size:

This action also allows you to use Email Templates (both Classic and Lightning), so long as you provide it with a recordId to a Contact, Lead, or User that can be used to fill in the merge fields of the template:

To make it easy to pass email addresses into the action, it supports any combination of the following, for To, CC, and BCC:

  • A single email address
  • A string collection of email addresses
  • A collection of Contacts
  • A collection of Users
  • A collection of Leads

Other supported features include:

  • Support for Organization-Wide Email Addresses
  • Support for Attachments
  • Ability to toggle on/off the use of the Salesforce per-user email signature
  • Ability to provide either a plain text body, an html body, or both
  • Ability to set the ReplyTo email address and the Sender Display Name

Instructions

This sample flow ships with the action and can be used to test and demonstrate the action:

Here’s how I have my inputs configured in the above sample Flow for an HTML body from a Text Template:

Here’s how it would be configured for use with an Email Template. Note the plainTextBody, HTMLbody, and Subject are all nulled out (when “Don’t Include” is selected, null values are used):

You can use any of these five combinations:

  • An HTML Body
  • A plain text body
  • Both an HTML Body or a plain text body
  • A Classic Email Template
  • A Lightning Email Template

However, you’ll get errors if you try to mix your own bodies and subjects with Email Templates.

Using Templates

If you want to use an Email Template, you must pass in the Id (not the name) of the template. In the above flow example, I use a Get Record to query for an email template by name, and then pass in the ID to the SendHTMLEmail flow action. Importantly, you need to also pass in the recordId of a Contact, Lead, or User that will serve as the context record for the template and populate the template’s merge fields. Do this with the templateTargetObjectID parameter

Setting the Sender/ReplyTo Address

You can either 1) use an OrganizationWideEmailAddress or 2) specify your own Reply-To Email Address and Sender Display Name. If you provide an OrganizationWideEmailAddress, that will take precedence and any Reply-To Email Address and/or Sender Display Name you’ve also provided will be ignored.

To use an OrganizationWideEmailAddress , pass the Id of one that you have defined into the action via the “Use This Organization-Wide Email Address Id”. (If you want to get the benefit of Verified sending, you can’t just paste the email address into the Reply-To Email Address field. You have to use the Use This Organization-Wide Email Address Id field.). to find the ID:

  1. In Lightning Setup, go to Organization-Wide Addresses and click Edit on the address you want to use:

2. Examine the URL of this web page. It should look something like this:

https://connect-dream-4759-dev-ed.lightning.force.com/lightning/setup/OrgWideEmailAddresses/page?address=%2F0D2560000008PGP%2Fe

3. The Id of the Organization-Wide Email Address is the character between the 2 “%2F” strings. So in the example above, you would extract “0D2560000008PGP” and insert it as an input:

Attachments

You can pass in a collection of Content Document Links. see this.

Considerations

This action makes use of the standard Salesforce email infrastructure, the same service that you use when you send a single email directly from a lightning experience page or a classic case feed. As such, any emails you send will be included in your usage, so be aware of the limits and guidelines. (Developer note: this action makes use of the Apex Messaging service API’s.)

This action does not use or involve Email Alerts, which are used in Workflow Rules and exist in Flow as separate actions you can drag into your flow. Be mindful of this so you don’t accidentally confuse the Email Alerts, the Email Templates, and the Flow Text Templates.

Currently unsupported features include:

  • Support for the MassEmailMessage API, enabling higher volumes
  • Character Set setting

Note that scratch orgs have a strict cutoff after sending just 50 email messages

If you’re interested in extending this class, please do so!


Installation

Old versions

1.2 Unmanaged (attachments are supported using Attachments instead of Content Document Links)

1.0 Unmanaged

1.0 – Managed (requires Winter ’20)

51 replies
      • daegan36
        daegan36 says:

        I’m haveing the same problem is there a setting I have to set? I was using 1.1 (didn’t notice the Not Working Notice) and getting ‘Null Pointer Exception Errors’. I uninstalled and installed both older versions 1.0. Now I can’t see the Action in the flow. Help.

        Reply
          • Tamar Erlich
            Tamar Erlich says:

            Hi Alex, I installed the new 1.3 version in my sandbox but it is not showing up in the action list and the sample flow is not loading it’s showing an error “source element container not defined”

  1. Megan Moody
    Megan Moody says:

    I was able to get this work – awesome! – but the sender comes through as unverified. I’m populating the replyEmailAddress variable with one of our org-wide email addresses. Is it because I’m sending from a sandbox? Will the behavior be different in production? Also, is there any trick to adding images to the text template being used for the HTML body? I added one, but it doesn’t go with the email. Thanks for any tips you can provide!

    Reply
  2. George
    George says:

    Amazing to have Lightning Emails available in a flow – thanks. Am I right in saying that this currently doesn’t support custom object merge fields in the template email – can only be merge fields on the contact, user or lead object?

    Reply
    • Alex Edelstein
      Alex Edelstein says:

      Yes, those are current limitations of Lightning Email Templates.

      Here’s how I’d solve this. I’d build a flow that creates a Contact record just to hold the custom information from the custom object record that I’m about to send email for. I’d populate the contact’s fields with my custom data. For example, I might set Contact.Description (which can be used in a Lightning Email Template as a merge field) to a Text Template string that includes a part number, a part name, and a billing code. I’d then save my new contact, getting the ID back into my flow. Then the same flow can use this Send Email to invoke a Lightning Email Template that uses that contact Id that’s now full of my custom object’s key data. Then I’d have the same flow delete the pseudo contact once the email is sent, although I might need to insert a 1 hour pause to make sure the contact doesn’t get deleted before the email system has time to pull the custom data from it!

      Reply
  3. Richard
    Richard says:

    Hello Alex,

    thanks a lot for your hard work, I am looking for that kind of solution for a long time. Unfortunately the link for the updated version (1.1 unmanaged) is not working. I only see “v0.1 Beta” in the version details and the testing flow is not opening at all (loading loop, so I can’t open it) after package installation.

    Can you provide a new link to the actual update?

    Thanks a lot!

    Reply
        • Richard
          Richard says:

          Hey Alex,

          thanks a lot, it works like a charm now.
          Do you think its somehow possible to get user input for the default template to work? I imagine a similar functionality like using a template in the activity timline were the user can alter the email template (except letterhead).
          Unfortunately flow input variables for rich text fields in aura components are not supported as far as I know. You have any other ideas?

          Reply
          • Alex Edelstein
            Alex Edelstein says:

            It’s doable with a little hackery. See my comment above that starts “Here’s how I’d do this”

  4. Nkosi
    Nkosi says:

    Hi, thanks a lot for your hard work . I am just having issues with a null pointer exception if I dont include an attachment and no email is being sent when attachments are included, no error but no email sent

    Reply
    • Alex Edelstein
      Alex Edelstein says:

      I’ll try to reproduce the no-attachment issue. The most common reason for email not being sent is that your org has hit its limits on email or isn’t enabled to send email. Are you using a scratch org?

      Reply
      • Alex Edelstein
        Alex Edelstein says:

        Can you confirm you’re getting a null pointer exception and not this error, which is similar but doesn’t involve pointers:

        Error element null (null).
        Flow encountered an error when processing and converting between data types. Please check the flow and ensure all data types are matched correctly.

        Reply
        • Johann moulin
          Johann moulin says:

          Hello Alex, thank you for this code. I have the same issue. I don’t think I have hit the limit and email are enabled in my org. Last message is a success but no email is sent. If I disable the attachment, it works fine. I use a collection of attachment (no need for cdl because my object uses attachments). Thank for your help

          Reply
          • Johann moulin
            Johann moulin says:

            Alex, I have tried with the conversion of cdl and it works fine. So when I create a collection of attachments, it doesn’t send the email, when I create a collection of cdl and I pass them through the convert action, it works fine. Hope it helps

      • Nkosi
        Nkosi says:

        Sorry for late response been on holiday, I now have an “Attempt to de-reference a null object error” not using attachments this time.

        Reply
  5. Moulin
    Moulin says:

    Well, I have solved this issue. When you get the attachment in your flow, you have to request all the fields (Id, Name, Contentype and Body). Once you have requested all these fields, it works fine.

    Reply
  6. dani
    dani says:

    Hi Alex,
    thank you for this development, is there any chance when send the email , save it under the activity history ?

    Reply
      • dani
        dani says:

        thanks Alex, i am aware of this option, but can your component work as the standard quick action of send email? i mean when you send an email to a non contact or lead, an activity history of the email recorded under the record and also the html body not broken (if you use tasks the html body will appear with the tags)

        Reply
  7. Derek Hawley
    Derek Hawley says:

    I really appreciate all the work you do with Flows and the time you dedicate. This website has been a huge asset for me. I wanted to ask if there is a way for this to work with an email relay? When using the simple email action, emails are sent from my email relay. When sending emails using SendHTMLEmail Action they are sent via the Salesforce domain.

    Thanks for the help.

    Reply
    • Alex Edelstein
      Alex Edelstein says:

      Derek, I don’t know much about relays. From what I read, it sounds like it’s an org config thing and not something this action would control. May I suggest you ask support on behalf of your company “I’m using an apex class that sends email but it’s not using my existing relay” and see if they can help you pin it down.

      Reply
  8. Tamar Erlich
    Tamar Erlich says:

    Hi Alex, can this functionality be extended to use an email field or variable to specify the sender email (e.g. I want the email to come from the contact owner’s manager or the SE on the contact’s account team)
    Thank you for all the amazing work you do for the Flowhana

    Reply
  9. Gidi Abramovich
    Gidi Abramovich says:

    Alex Hi,
    Your Email solution is great!!!
    We are finally able to receive rich text emails without HTML tags 🙂
    Is it possible to add multiple recipients’ emails with comma-separated?

    It will be great if we could define a Public Group as a recipient, so all of its Group Members will receive the email.

    Thanks a lot for the hard work you are doing!

    Gidi

    Reply
  10. Richard
    Richard says:

    Toggle signature on / off doesnt seem to do anything. Current user’s salesforce signature gets added into the email no matter what. Can we fix this 🙂

    Reply
  11. Anonymous
    Anonymous says:

    Hi Alex,

    Merge field option is just for contact lead and users in classic and lightning templates both. Is this correct ? will not work for any other objects.

    Also I installed the package in sandbox but send html email action does not appear.

    Reply
    • Alex Edelstein
      Alex Edelstein says:

      While the merge field options for templates are limited, you can use Flow to work around that. See the paragraph above that starts “Here’s how I’d solve this.”

      I was able to get the action to install on sandbox orgs. Unless we get more problem reports, this is probably something specific to your org. Make sure you’re using version 1.3 above.

      Reply
  12. Josh Dayment
    Josh Dayment says:

    Is the inline image still a bug I have tried copy and pasting as well as using the image button via the text template editor but images are still coming through broken in the email.

    Reply
  13. Megan Moody
    Megan Moody says:

    I just installed and tested 1.31. The email sends great, however, it’s not adding a copy of the actual email to the case feed. Is there a way to do this? I am pretty sure a previous version of this did this. I tried setting saveAsActivity to TRUE, but that just logs that an email was sent and doesn’t display the actual email sent. I am trying to send via a template.

    Reply
    • Megan Moody
      Megan Moody says:

      I also tried sending via an HTML body from the action itself (vs. a template) and that didn’t save the actual email to the feed either.

      Reply
      • Megan Moody
        Megan Moody says:

        What I ended up doing was adding the following to the code below setting of the subject:

        // Log the email to the feed of the record
        mail.setWhatId(recordId);

        Because of the business requirements, I needed to log the actual email sent to the user. The above did that. Thank you!

        Reply
  14. Wendy Tanner
    Wendy Tanner says:

    Is there an option to review the email before sending it? This looks like a solution, but the team wants to choose the template then review before sending.

    Reply
    • Alex Edelstein
      Alex Edelstein says:

      I’d tackle that problem by putting a Decision element in the flow that asks 1) send a single email to ___insert email___ for verification or 2) send normally. Or break it up into two flows. You could get fancier and insert a link into the test message that the reviewer could click to authorize the main send to take place.

      Reply
  15. Jem
    Jem says:

    I tested this on Sandbox and it works well but when I tried in prod it only works if its triggered by users or PB but not with scheduled flow. :'(

    Reply
    • Josh Dayment
      Josh Dayment says:

      I have a flow where I do something similar where I store the email body in a variable and display that variable on a screen using display text. I also have another version where we actually store the email in a custom object (very specific use case) then I use the recorddetail component to actually update the email body.

      Reply

Trackbacks & Pingbacks

  1. […] a Flow that uses the Send Rich Email action. Use the “Autolaunched” Flow Type. Configure the flow with input variables to capture […]

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply