In addition to providing a card-based interface when a user is reading a Gmail message, Gmail add-ons can provide another interface when the user is composing new messages or replying to existing ones. This allows Gmail add-ons to automate the task of composing emails for the user.
A Gmail add-on can implement an extended message UI, an extended compose UI, or both. You can add universal actions as well.
Accessing the add-on compose UI
When a user attempts to compose a new message in Gmail, any add-ons that provide a compose UI appear in the bottom icon row of the compose window. Each icon represents a compose action for that add-on. Clicking on a compose action icon causes a corresponding compose trigger function to execute. The compose trigger function builds the compose UI for that compose action, which Gmail then displays to the user.
Building a compose add-on
You can add compose functionality to an add-on by following these general steps:
- Add the
gmail.composeTrigger
field to the add-on script project manifest and update the manifest scopes to include those required for compose actions. - Implement a compose trigger function that builds a compose UI when the user selects the compose action in the Gmail compose window. Compose trigger functions return an array of cards that comprise the compose UI for the compose action.
- Implement associated callback functions needed to react to the user's
compose UI interactions. These functions are not the compose action itself
(which only causes the compose UI to appear); rather, these are the
individual functions that govern what happens when different elements of the
compose UI are selected. For example, a compose UI containing a button
usually has an associated callback function that executes when a user clicks
that button. The callback function for widgets that update the draft message
content should return a
UpdateDraftActionResponse
object.
Compose trigger function
An add-on's compose UI is built the same way as the add-on's message UI—using the Apps Script Card service to construct cards and fill them with widgets.
You must implement the gmail.composeTrigger.selectActions[].runFunction
that you define in your manifest. The compose trigger function must return
an array of cards that comprise the compose
UI for that action. These functions are very similar to
contextual trigger functions
and should build cards in the same way.
Compose trigger event objects
When a compose action is selected, it executes the corresponding compose trigger function and passes the function an event object as a parameter. The event object can carry information about the draft being composed and the client platform to the trigger function.
If the gmail.composeTrigger.draftAccess
manifest field is
NONE
or isn't included, the event object has only minimal information.
If gmail.composeTrigger.draftAccess
is set to METADATA
, the event object
passed to the compose trigger function is populated with lists of recipients
of the email being composed.
The following table describes the event object fields:
Property | Type | Description |
---|---|---|
clientPlatform |
string |
Indicates where the event originates (web, iOS, or Android). |
formInput |
object{string, string} |
For compose trigger functions, this is an empty object. |
formInputs |
object{string, string[]} |
For compose trigger functions, this is an empty object. |
parameters |
object{string, string} |
For compose trigger functions, this is an empty object. |
draftMetadata |
object{string, string[]} |
Only present if manifest draftAccess is
METADATA . An object containing metadata for the email
being composed.
|
draftMetadata.toRecipients |
string[] |
Only present if manifest draftAccess is
METADATA . A list of email addresses from the email's
"To:" field.
|
draftMetadata.ccRecipients |
string[] |
Only present if manifest draftAccess is
METADATA . A list of email addresses from the email's
"CC:" field.
|
draftMetadata.bccRecipients |
string[] |
Only present if manifest draftAccess is
METADATA . A list of email addresses from the email's
"BCC:" field.
|
Inserting content into active drafts
Typically an add-on compose UI provides the user options and control that help compose a message. Once the user has made selections in the UI, the add-on interprets the selections and updates the current working email draft accordingly.
To make it easier to update the current draft email, the Card service has been extended with the following classes:
ContentType
—An enum that defines whether to add mutable HTML, immutable HTML (which Gmail users can't edit), or plain text content.UpdateDraftActionResponse
—Represents a response to an action that updates the current draft email.UpdateDraftActionResponseBuilder
—A builder forUpdateDraftActionResponse
objects.UpdateDraftBodyAction
—Represents an action that update the body of the current draft email.UpdateDraftBodyType
—An enum that defines how the body is changed.
Typically an add-on compose UI includes a 'Save' or 'Insert' widget that a user
can click to indicate they are done making selections in the UI and want their
choices to be added to the email they are composing. To add this
interactivity, the widget should have
an associated Action
object that
instructs the add-on to run a specific callback function when the widget is
clicked.
You must implement these callback functions. Each callback function should
return a built
UpdateDraftActionResponse
object that details the changes to make to the current draft email.
Example
The following code snippet shows how to build a compose UI that inserts images into the current draft email.
/**
* Compose trigger function that fires when the compose action is
* selected. Builds and returns a compose UI for inserting images.
*
* @param {event} e The compose trigger event object. Not used in
* this example.
* @return {Card[]}
*/
function getInsertImageComposeUI(e) {
return [buildImageComposeCard()];
}
/**
* Build a card to display images from a third-party source.
*
* @return {Card}
*/
function buildImageComposeCard() {
// Get a list of image URLs to display in the UI.
// This function is not shown in this example.
var imageUrls = getImageUrls();
var card = CardService.newCardBuilder();
var cardSection = CardService.newCardSection().setHeader('My Images');
for (var i = 0; i < imageUrls.length; i++) {
var imageUrl = imageUrls[i];
cardSection.addWidget(
CardService.newImage()
.setImageUrl(imageUrl)
.setOnClickAction(CardService.newAction()
.setFunctionName('applyInsertImageAction')
.setParameters({'url' : imageUrl})));
}
return card.addSection(cardSection).build();
}
/**
* Adds an image to the current draft email when the image is clicked
* in the compose UI. The image is inserted at the current cursor
* location. If any content of the email draft is currently selected,
* it is deleted and replaced with the image.
*
* Note: this is not the compose action, but rather an action taken
* when the user interacts with the compose action's corresponding UI.
*
* @param {event} e The incoming event object.
* @return {UpdateDraftActionResponse}
*/
function applyInsertImageAction(e) {
var imageUrl = e.parameters.url;
var imageHtmlContent = '<img style=\"display: block\" src=\"'
+ imageUrl + '\"/>';
var response = CardService.newUpdateDraftActionResponseBuilder()
.setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction()
.addUpdateContent(
imageHtmlContent,
CardService.ContentType.MUTABLE_HTML)
.setUpdateType(
CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
.build();
return response;
}