0

I want to update signature of a domain user via Google Apps Script as G Suite administrator.

I followed Mike's example here using HTTP Request to the Gmail API and was able to it to work.

Here is the summary what I did:

The following code works GREAT (see original version here)

function setSignatureWithHTTPRequest(email, signature) {
  var signatureSetSuccessfully = false;
  var authorizationScope = ['https://www.googleapis.com/auth/gmail.settings.sharing'];
  
  var service = getDomainWideDelegationService("Gmail: ", authorizationScope, email);

  if (!service.hasAccess()) {
    Logger.log("failed to authenticate as user " + email);
    Logger.log(service.getLastError());

    signatureSetSuccessfully = service.getLastError();

    return signatureSetSuccessfully;
  } else {
    Logger.log("successfully authenticated as user " + email);
  }
  
  var username = email.split("@")[0];
  var resource = { signature: signature };
  
  var requestBody                = {};
  requestBody.headers            = {"Authorization": "Bearer " + service.getAccessToken()};
  requestBody.contentType        = "application/json";
  requestBody.method             = "PUT";
  requestBody.payload            = JSON.stringify(resource);
  requestBody.muteHttpExceptions = false;

  var emailForUrl = encodeURIComponent(email);

  var url = "https://www.googleapis.com/gmail/v1/users/me/settings/sendAs/" + emailForUrl;

  try {
    var setSignatureResponse = UrlFetchApp.fetch(url, requestBody);
    signatureSetSuccessfully = true;
    Logger.log("setSignatureResponse on successful attempt:" + setSignatureResponse);
  } catch (e) {
    Logger.log("Set signature with HTTP request failed: " + e);
  }
  
  return signatureSetSuccessfully;
}

However, when I modify the code to use the patch method from the Gmail API instead of HTTP Request with UrlFetchApp, I get a GoogleJsonResponseException: Not Found error.

function setSignatureWithMethod(email, signature) {
  var signatureSetSuccessfully = false;
  var authorizationScope = ['https://www.googleapis.com/auth/gmail.settings.sharing'];
  
  var service = getDomainWideDelegationService("Gmail: ", authorizationScope, email);

  if (!service.hasAccess()) {
    Logger.log("failed to authenticate as user " + email);
    Logger.log(service.getLastError());

    signatureSetSuccessfully = service.getLastError();

    return signatureSetSuccessfully;
  } else {
    Logger.log("successfully authenticated as user " + email);
  }
  
  var resource = { signature: signature };
  
  try {
    var setSignatureResponse = Gmail.Users.Settings.SendAs.patch(resource, "me", email);
    Logger.log("setSignatureResponse on successful attempt:" + setSignatureResponse);
    signatureSetSuccessfully = true;
  } catch (e) {
    Logger.log("Set signature with method failed: " + e);
  }

  return signatureSetSuccessfully;
}

My question is twofold.

  • Why function setSignatureWithMethod() generates error?

  • Another poster mentioned here that "...you will need to use the Gmail REST interface using UrlFetchApp service to make the calls instead of the Gmail service...because scripts can not run as a service account, only a user account." Is this accurate? Are the methods provided by the Gmail API (list, patch, update, etc.) are only for setting your own email signature (or own Gmail settings) and not for other user in the domain?

s2000coder
  • 913
  • 2
  • 15
  • 23

1 Answers1

0

Ok, two things.

1 - Gmail.Users.Settings.SendAs.patch() won't work. I think that's either an example of how the Gmail API would be implemented in any language, or it's part of a Java library provided by Google which can't be used in Apps Script.

Try changing this line:

var setSignatureResponse = Gmail.Users.Settings.SendAs.patch(resource, "me", email);

to this block:

var requestBody                = {};
requestBody.headers            = {"Authorization": "Bearer " + service.getAccessToken()};
requestBody.contentType        = "application/json";
requestBody.method             = "PATCH";
requestBody.payload            = JSON.stringify(resource);
requestBody.muteHttpExceptions = false;

var emailForUrl = encodeURIComponent(email);

var url = "https://www.googleapis.com/gmail/v1/users/me/settings/sendAs/" + emailForUrl;

try {

  var setSignatureResponse = UrlFetchApp.fetch(url, requestBody);

  signatureSetSuccessfully = true;

  Logger.log("setSignatureResponse on successful attempt:" + setSignatureResponse);

} catch (e) {

  Logger.log("Set signature with HTTP request failed: " + e.message);

}

2 - Not sure if this matters but you're sending an array as the authorization scope, but my original example and all my working code uses a string.

Try changing this:

var authorizationScope = ['https://www.googleapis.com/auth/gmail.settings.sharing'];

to this...

var authorizationScope = 'https://www.googleapis.com/auth/gmail.settings.sharing';
Employee
  • 2,231
  • 3
  • 33
  • 60
  • Yeah I figure Gmail.Users.Settings.SendAs.patch() on your own settings and not for other domain users. I read somewhere that the only way to specify multiple scopes is by putting them in an array. Also, as I mentioned, using UrlFetcheApp.fetch() for HTTP request worked. I was just wondering why using the method providing by the Gmail API yielded an error. – s2000coder Apr 20 '18 at 04:49
  • 1
    Ok, well to just answer your question about why that patch() method wouldn't work in theory, I would say it's because you wouldn't be sending in any authorization headers or the access token - you're just sending in `resource`, `"me"`, and `email`, but no authorization. This line in my answer is what includes the authorization info in the API call: `requestBody.headers = {"Authorization": "Bearer " + service.getAccessToken()};` – Employee Apr 23 '18 at 22:01