3

Background:

Google Workspace Add-ons for Gmail allow access the currently-open email in the API on contextualTrigger with the scope:

https://www.googleapis.com/auth/gmail.addons.current.message.readonly

An access token must be passed using GmailApp.setCurrentMessageAccessToken(accessToken) in order to grant access to this currently opened email:

var accessToken = e.gmail.accessToken;
var messageId = e.gmail.messageId;

// The following function enables short-lived access to the current
// message in Gmail. Access to other Gmail messages or data isn't
// permitted.
GmailApp.setCurrentMessageAccessToken(accessToken);
var mailMessage = GmailApp.getMessageById(messageId);

From the above documentation:

setCurrentMessageAccessToken(accessToken)

Sets the current message access token that enables the script to access the current GmailMessage properties.

Only Gmail add-on projects using Gmail current message scopes require this method.

Unfortunately, the link to the pages on access tokens and current message scopes are at current both broken and result in 404 pages, so I can't find out more information from here.

Question:

How can one achieve the same funcitonality using the Gmail API directly instead of GmailApp?

The documentation for Gmail: users.messages.get states that https://www.googleapis.com/auth/gmail.addons.current.message.readonly is a valid scope to call this method, however, there does not seem to be an equivalent of GmailApp.setCurrentMessageAccessToken(accessToken) for the Gmail API.

Things that do not work:

  • Using ScriptApp.getOAuthToken() - as per this documentation, "The access token than enables Gmail scopes is not the same as the access token returned by ScriptApp.getOAuthToken(). You must use the token provided in the action event object."
  • Providing the access token from the event object as the token in the Authorization: Bearer header also throws a 403 error.

The saught functionality would akin to:

var accessToken = e.gmail.accessToken
var messageId = e.gmail.messageId

Gmail.setCurrentMessageAccessToken(accessToken) // made up method
var mailMessage = Gmail.Users.Messages.get("me", messageId)
Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54
  • Although I'm not sure whether I could correctly understand about your question, I proposed an answer. Could you please confirm it? If I misunderstood your question and that was not the direction you expect, I apologize. – Tanaike Apr 23 '21 at 08:06

2 Answers2

3

I think that in that case, in order to include the access token, how about directly requesting to the endpoint of the Gmail API using UrlFetchApp? When your script is converted, it becomes as follows. In this case, the scope can be selected from Authorization Scopes.

Sample script:

var accessToken = "###";
var messageId = "###";
var userId = "me";
var url = `https://gmail.googleapis.com/gmail/v1/users/${userId}/messages/${messageId}`;
var res = UrlFetchApp.fetch(url, {headers: {authorization: `Bearer ${accessToken}`}});
console.log(res.getContentText())

Note:

  • In this case, please be carefult about the scopes. Ref

References:

Added:

Your goal is as follows.

You want to use the method of "users.messages.get" of Gmail API using the scope of gmail.addons.current.message.readonly.

From our discussions in the comment, I summarized the current situation as follows.

  • When I checked the including scopes from the access token retrieved by ScriptApp.getOAuthToken() for the GAS project which set the manifest file, I could confirm that the scopes of gmail.addons.current.message.readonly and script.external_request.

  • When I saw the official document, in order to use the method of "users.messages.get", gmail.addons.current.message.readonly is shown as Requires one of the following OAuth scopes:.

  • But, when the scope of gmail.addons.current.message.readonly is used for the method of "users.messages.get", such error like Missing access token for authorization. occurs.

  • When the scope of gmail.readonly is included, the error could be removed.

From above situation, how about reporting this to the Google issue tracker? Ref

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • In this case, where can you get the value for `accessToken`? `e.gmail.accessToken` is used, then the error `Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.` is given by the API. If `ScriptApp.getOauthToken()` is used, then the error given by the API is `GoogleJsonResponseException: API call to gmail.users.messages.get failed with error: Missing access token for authorization.` – Rafa Guillermo Apr 23 '21 at 08:13
  • @Rafa Guillermo Thank you for replying. I apologize for the inconvenience. Now, I could replicate your situation. In my case, when the scopes of `https://www.googleapis.com/auth/script.external_request` and `https://www.googleapis.com/auth/gmail.addons.current.message.readonly` are used, such error occurred. For this, when I added a scope of `https://www.googleapis.com/auth/gmail.readonly`, the error could be removed. It seems that the scope of `gmail.readonly` is required to be used. If this was not the direction you expect, I apologize again. – Tanaike Apr 23 '21 at 08:35
  • Hi @Tanaike, thank you for your reply. Unfortunately it is important for me to use the `https://www.googleapis.com/auth/gmail.addons.current.message.readonly` scope as this is used in a Google Workspace add-on, and I would like to avoid using restricted scopes such as `https://www.googleapis.com/auth/gmail.readonly`. I am unsure how to use `gmail.addons.current.message.readonly` without using GmailApp. – Rafa Guillermo Apr 23 '21 at 08:40
  • @Rafa Guillermo Thank you for replying. I would like to confirm your goal. In your situation, both scopes of `gmail.addons.current.message.readonly` and `gmail.readonly` cannot be used. You are required to use the method of " users.messages.get" of Gmail API using only the scope of `gmail.addons.current.message.readonly`. Is my understanding correct? – Tanaike Apr 23 '21 at 08:42
  • Yes, that's correct, as per the documentation for `messages.get`, `gmail.addons.current.message.readonly` should be a valid scope https://developers.google.com/gmail/api/reference/rest/v1/users.messages/get#authorization-scopes – Rafa Guillermo Apr 23 '21 at 08:49
  • @Rafa Guillermo Thank you for replying. I summarized our discussions in my answer. Could you please confirm it? – Tanaike Apr 23 '21 at 08:56
  • @Rafa Guillermo I found this issue tracker. https://issuetracker.google.com/issues/111084656 I thought your situation might be related to this. But, it seems that the response has still not been posted. So I'm not sure whether this is the bug or the current specification. I apologize for this. – Tanaike Apr 24 '21 at 08:10
  • Hi @Tanaike, thank you for your help. With your answer, and digging further, it seems that it's not possible at the moment. I will file a feature request to expose labeling individual messages with GmailApp. – Rafa Guillermo Apr 27 '21 at 08:22
  • @Rafa Guillermo Thank you for replying. In the current stage, unfortunately, I cannot find the workaround. When I found it, I would like to tell here. By the way, from your answer, I added a star to your Future Request. Thank you, too. – Tanaike Apr 27 '21 at 13:03
  • 1
    Thank you @Tanaike. If/When I find a solution I will post it and let you know. Thanks for looking over it and giving the feature request the star! – Rafa Guillermo Apr 27 '21 at 13:15
2

Answer:

At the moment, this is not possible to do.

Issue rundown:

  • GmailApp has no method or class to allow labels to be manipulated on individual messages, only threads.
  • The accessToken provided in the contextual trigger appears to be distinct to the OAuth token and so can not be used to authenticate the call to read the current message.
  • There is no way to pass the token via the Gmail API so that the current message can be used.
  • The only way to get the message is if a scope such as gmail.readonly is used.
  • While https://www.googleapis.com/auth/gmail.addons.current.message.readonly is listed as a valid scope for messages.get, there does not appear to be any way to actually use the scope when connecting to the Gmail API.

Further steps:

  • I have filed a feature request here to add the ability to manipulate message labels from the GmailApp class in Apps Script. Please star this issue to see its priority increased.
    • On this note, there was a feature request for this already at this page for the same feature, but as it is over two years old without a response from Google I have filed another.
  • I have filed documentation feedback for messages.get using the Send feedback button to either have the scope gmail.addons.current.message.readonly clarified, or removed from the page.
Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54