Lightning Web Components for Your Inbox | Salesforce Developers Blog

Believe it or not, since the Summer ’19 release, you have been able to bring Lightning Components right into your inbox through our Gmail and Outlook integrations. Since then, the introduction of Lightning Web Components and the ever-growing ecosystem around them has made it possible to enhance your email experience. Let’s take a look at how you can craft Lightning Components for your inbox and bring your users closer to their Salesforce data.

Components for your inbox

Before we get started, it’s important to note that these components require that your company have an enterprise email account and either the Outlook Add-in or the Chrome Extension for Salesforce. Both of these solutions bring in a Salesforce Lightning sidebar into your browser for you to interact with.

Building components for the Lightning sidebar

You can bring any LWC you’ve already built right into your inbox’s sidebar by exposing it in your components js-meta.xml file and adding lightning__Inbox as a target.

<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <isExposed>true</isExposed>
    <apiVersion>52.0</apiVersion>
    <targets>
        <target>lightning__Inbox</target>
    </targets>
    <description>Sample Email Application Pane</description>
</LightningComponentBundle>

By doing this, you are making the component available to the Lightning sidebar, as well as exposing the messagebody, subject, and people properties as public. You can assign the values in the JavaScript file by adding the @api decorator to each property.

import {LightningElement, api} from 'lwc';

export default class SampleEmailAppPane extends LightningElement {
    @api messageBody;
    @api subject;
    @api people;
}
  • messageBody is populated with the text content of the email or calendar item
  • subject is populated with the subject line of the email or calendar item
  • people is populated with all of the people that may be associated with the email or calendar item

While the message body and subject are quite straight forward, the people data structure is slightly more complex. The to, cc, and bcc items contain arrays, while the from item is an object.

Here is an example of a payload that would be passed into the people property:

{
  "to": [
    {
      "name": "Cindi Quant",
      "email": "cquant0@example.com"
    }
  ],
  "cc": [
    {
      "name": "Arleta Perrigo",
      "email": "aperrigo1@example.com"
    },
    {
      "name": "April Rennocks",
      "email": "arennocks@example.com"
    },
  ],
  "bcc": [],
  "from": {
    "email": "srodriguez@example.com",
    "name": "Sarah Rodriguez",
    "replyTo": "srodriguez@example.com"
  }
}

Using components in the App Builder

In this example, we’re going to talk about components in the Gmail sidebar; however, you can always reference the outlook integration documentation for examples.

To get started, all you need to do is navigate to Salesforce Setup > Gmail Integration and Sync. From there, you can turn on the Gmail integration and switch on Customize Content with App Builder. Once this is active, you can select Create New Pane to launch an app builder for your new email application pane—this functions just like the App Builder you know and love. It allows you to bring in standard and custom components, as well as managed components from AppExchange partners!

Building a custom LWC for the email application pane

Let’s take a look at how we can build a Lightning Web Component that can check to see if anyone in the email chain is a contact named on an opportunity. In order to achieve this, the first thing we need to do in our Lightning Web Component would be to collate all of the people in the thread and aggregate them into a single object. We can do this by checking the values of the items and pushing them into a single array.

The code block below will show you how this is done by collating each of the of the people into an array.

inboxOpportunityContactRoles.js

export default class InboxOpportunityContactRoles extends LightningElement {
    @api people;
    emailAddresses;
    oppContacts;
    connectedCallback() {
        if (this.people) {
            let emailArray = [];
            if (this.people.from) {
                emailArray.push(this.people.from.email)
            }
            if (this.people.cc) {
                this.people.cc.forEach((person) =>
                    emailArray.push(person.email)
                );
            }
            if (this.people.bcc) {
                this.people.bcc.forEach((person) =>
                    emailArray.push(person.email)
                );
            }
            this.emailAddresses = JSON.stringify(emailArray);
        }
    }
}

Once we’ve consolidated the object down to a list of email addresses, we can pass this into Apex to get the opportunity contact roles with their opportunity details. In Apex, we can use a subquery to get the opportunity contact roles from the opportunity and then filter the opportunity by the contacts who’s email address are in the list. It’s worth noting that the maximum about of people included in the email is 500.

inboxOpportunityContactController.cls

public with sharing class InboxOpportunityContactController {
  @AuraEnabled(cacheable=true)
  public static List<Opportunity> getOpportunityContactDetails(
    List<String> emailAddresses
  ) {
    List<Opportunity> oppWithContacts = [
      SELECT
        Name,
        Amount,
        (SELECT Id, Contact.Name, Role FROM OpportunityContactRoles)
      FROM Opportunity
      WHERE
        Id IN (
          SELECT OpportunityId
          FROM OpportunityContactRole
          WHERE Contact.Email IN :emailAddresses
        )
    ];
    return oppWithContacts;
  }
}

Once we have written the getOpportunityContactDetails Apex method, we can then use a @wire decorator to pass in the email address and retrieve the data.

inboxOpportunityContactRoles.js

@wire(getOppContactDetails, { emailAddresses: '$emailAddresses' })
wiredOppContacts({ error, data }) {
    if (data) {
        this.oppContacts = data;
        this.error = undefined;
    } else if (error) {
        this.error = error;
        this.oppContacts = undefined;
    }
}

Once the emailAddress property is populated, it will run the wire and assign the results to the oppContacts property. In the component’s HTML file, we can iterate over oppContacts to render the data.

inboxOpportunityContactRoles.html

<template>
  <template for:each={oppContacts} for:item="opportunity" for:index="i">
    <li  key={opportunity.i}>
      <div>{opportunity.Name}</div>
      <div>Amount: ${opportunity.Amount}</div>
      <div>Contact Roles</div>
      <ol >
        <template for:each={opportunity.OpportunityContactRoles} 
          for:item="oppContact"
          for:index="i">
          <li key={oppContact.i}>
            <div>{oppContact.Contact.Name} - {oppContact.Role}</div>
          </li>
        </template>
      </ol>
    </li>
  </template>
</template>

Our component in action!

You can see that once the component is added to the sidebar, it will render each time you view and email in your inbox!Lighting component inside Gmail

Conclusion

Creating Lighting Web Components for your email client can really enhance your team’s experience and productivity. Check out the developer guide to learn more about what developers can create with LWC in the Lightning sidebar.

Ready to create your first LWC? Check out our getting started trail and our LWC Recipes app. Have a great Lightning sidebar component? Show us on Twitter @SalesforceDevs.

About the author

Stephan Chandler-Garcia is a Senior Developer Evangelist at Salesforce. He focuses on application development, security, and communities. You can follow him on Twitter @stephanwcg.

Stay up to date with the latest news from the Salesforce Developers Blog

Subscribe