2

I'm just trying to get started with the sample addon Google describes here for extending the compose UI: https://developers.google.com/gsuite/add-ons/gmail/extending-compose-ui

However when I run it I'm getting this error:

Error with the add-on. Run time error. Cannot return a card markup from the callback function of a universal action.

I have not setup any universal actions in my manifest file:

{
  "timeZone": "America/New_York",
  "oauthScopes":[
    "https://www.googleapis.com/auth/script.send_mail",
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/gmail.addons.execute",
    "https://www.googleapis.com/auth/gmail.addons.current.message.metadata",
    "https://www.googleapis.com/auth/gmail.modify",
    "https://www.googleapis.com/auth/gmail.addons.current.action.compose"
    ],
  "gmail":{
    "name": "My Mail Merge",
    "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/label_googblue_24dp.png",
    "composeTrigger": {
      "draftAccess": "METADATA",
      "selectActions": [
        {
          "text": "show UI",
          "runFunction": "buildImageComposeCard"
        }
      ]
    },
    "openLinkUrlPrefixes": [
      "https://mail.google.com/"
      ],
    "primaryColor": "#42585F4",
    "secondaryColor": "#42585F4"
  },
  "exceptionLogging": "STACKDRIVER"
}

Below is Code.gs:

function getInsertImageComposeUI(e) {
  return [buildImageComposeCard()];
}

function buildImageComposeCard() {
  // Get a list of image URLs to display in the UI.
  // This function is not shown in this example.
  var imageUrls  = [
    "https://mail.google.com/1",
    "https://mail.google.com/2",
    "https://mail.google.com/3"
    ];

  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();
}

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.HTML)
                            .setUpdateType(
                              CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
  .build();
  return response;
}
Michael
  • 1,428
  • 3
  • 15
  • 34
  • I couldn't get this working either. I'd move on to something else if I were you. Perhaps someone here will have a better answer but this example harkens to the days a decade ago when it was pretty much impossible for one with average intelliigence to even consider having a chance at figuring out how an example actually works. – Cooper Mar 21 '19 at 17:55
  • Haha. Well, I would find a Gmail addon quite useful to my employer so am motivated to find a way to work. Will reach out to Google directly and see if they can help. Stackoverflow is their 1st line of support for apps script stuff, but not the last. – Michael Mar 21 '19 at 18:01
  • By no means do I know as much as many other volunteers here so all is not lost yet. I have written Gmail Addons but not composer addons. – Cooper Mar 21 '19 at 18:03
  • I too was able to get the sidebar stuff to work, just not the compose stuff. – Michael Mar 21 '19 at 18:13
  • Any updates from google? or with developing the addon? – mtleis Nov 09 '19 at 15:13

3 Answers3

0

In the manifest file, runFunction has to be set to "getInsertImageComposeUI",

Also, in the code file, CardService.ContentType.HTML has to be one of

CardService.ContentType.MUTABLE_HTML

or

CardService.ContentType.IMMUTABLE_HTML
tehhowch
  • 9,645
  • 4
  • 24
  • 42
Michael
  • 1,428
  • 3
  • 15
  • 34
  • I have the same issue. Already set the runFunction and ContentType to what you suggested but it didn't work. Any other suggestions? – mtleis Nov 09 '19 at 15:12
0

I have the same error message and couldn't get that example to work. However, I created a simpler Hello-World example that actually works. I think it is more useful for newbies to start with. Don't forget to set the runFunction in the manifest to getComposeCard.

function getComposeCard(e) {   return [buildComposeCard()]; }

function buildComposeCard() {
    var card = CardService.newCardBuilder();   
    var cardSection = CardService.newCardSection().setHeader('Test Header');   
    testVar = ['item1', 'item2'];   
    for (var i = 0; i < testVar.length; i++) {
        var item = testVar[i];
        cardSection.addWidget(
          CardService.newTextParagraph().setText(item));   
   }   
   return card.addSection(cardSection).build(); 

}

mtleis
  • 712
  • 1
  • 9
  • 28
0

Probably it's way too late, but the problem can be fixed by simply wrap the result of buildImageComposeCard as array

return [card.addSection(cardSection).build()]