限制 Google 应用脚本的 OAuth 范围

Limiting OAuth scope for Google App Script

我试图在提交表单后发送电子邮件的脚本中限制我的 OAuth 范围。我想对其进行限制,以使其所需的权限最少。如果我单击 运行,它会尝试授予正确的权限。如果我设置表单提交触发器,它想要授权读取、更改、删​​除所有 spreadsheets 和更改所有表单。

如果我授予脚本对 sheet 和表单的完全访问权限,它会按预期 运行 进行。我只是想减少一些权限。屏幕截图显示它正在请求比 appsscript.json 文件中指定的权限更多的权限。

此脚本附加到从我的表单生成的回复 sheet。

来自我的 appsscript.json:

"oauthScopes": [
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/gmail.send",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/forms.currentonly",
    "https://www.googleapis.com/auth/spreadsheets.currentonly"
  ]

代码:

/**
 * @OnlyCurrentDoc
 */

function onFormSubmit(e) {
  var values = e.namedValues;

  var htmlBody = 'Hey ' + values['Name of Recipient'] + "!<br>";
  htmlBody += values['Name of Sender'] + " thinks you deserve a shoutout! Thank you for being so awesome!";
  htmlBody += '<br> <em>' + values['Shoutout'] + " - " + values['Name of Sender'] + "</em>";
  htmlBody += '<br><br>';

  GmailApp.sendEmail(values['Recipient Email'],'SHOUT OUT!!!!!!','',
  {from:'email@domain.com',
  htmlBody:htmlBody});
}

Google Form/Sheet Questions/Columns

OAuth 权限截图:

项目详细信息 OAuth 范围:

我相信你的目标如下。

  • 从你的问题来看,你想限制 The code: 的显示脚本的范围,如下所示。

      /**
       * @OnlyCurrentDoc
       */
    
      function onFormSubmit(e) {
        var values = e.namedValues;
    
        var htmlBody = 'Hey ' + values['Name of Recipient'] + "!<br>";
        htmlBody += values['Name of Sender'] + " thinks you deserve a shoutout! Thank you for being so awesome!";
        htmlBody += '<br> <em>' + values['Shoutout'] + " - " + values['Name of Sender'] + "</em>";
        htmlBody += '<br><br>';
    
        GmailApp.sendEmail(values['Recipient Email'],'SHOUT OUT!!!!!!','',
        {from:'email@domain.com',
        htmlBody:htmlBody});
      }
    

使用Gmail 服务GmailApp.sendEmail 时,范围似乎不变为https://mail.google.com/。这似乎是当前的规范。所以当你想限制范围时,我认为你可以使用 Gmail API 来实现。当您的脚本使用 Gmail 转换后 API,它变成如下。

修改后的脚本:

在使用此脚本之前,please enable Gmail API at Advanced Google services

/**
 * @OnlyCurrentDoc
 */

// This is from 
function convert_(toEmail, fromEmail, subject, textBody, htmlBody) {
  const boundary = "boundaryboundary";
  const mailData = [
    `MIME-Version: 1.0`,
    `To: ${toEmail}`,
    `From: ${fromEmail}`,
    `Subject: =?UTF-8?B?${Utilities.base64Encode(subject, Utilities.Charset.UTF_8)}?=`,
    `Content-Type: multipart/alternative; boundary=${boundary}`,
    ``,
    `--${boundary}`,
    `Content-Type: text/plain; charset=UTF-8`,
    ``,
    textBody,
    ``,
    `--${boundary}`,
    `Content-Type: text/html; charset=UTF-8`,
    `Content-Transfer-Encoding: base64`,
    ``,
    Utilities.base64Encode(htmlBody, Utilities.Charset.UTF_8),
    ``,
    `--${boundary}--`,
  ].join("\r\n");
  return Utilities.base64EncodeWebSafe(mailData);
}

function onFormSubmit(e) {
  var htmlBody = 'Hey ' + values['Name of Recipient'] + "!<br>";
  htmlBody += values['Name of Sender'] + " thinks you deserve a shoutout! Thank you for being so awesome!";
  htmlBody += '<br> <em>' + values['Shoutout'] + " - " + values['Name of Sender'] + "</em>";
  htmlBody += '<br><br>';

  var raw = convert_(values['Recipient Email'], 'email@domain.com', 'SHOUT OUT!!!!!!', "", htmlBody);
  Gmail.Users.Messages.send({raw: raw}, "me");
}
  • 在此脚本中,只能使用https://www.googleapis.com/auth/gmail.send的范围。

  • 在此示例脚本中,假定 e 是您要使用的正确值。请注意这一点。

注:

  • 关于"https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/forms.currentonly", "https://www.googleapis.com/auth/spreadsheets.currentonly"的其他范围,当我看到你的脚本时,那些范围不是必须使用的。但是,当使用 Google 表格时,可能需要使用 https://www.googleapis.com/auth/forms.currentonly。请注意这一点。

  • 例如,当您要使用其他方法时,请为它们添加作用域。我的答案是针对您在问题中显示的脚本。请注意这一点。

参考:

默认情况下,如果您添加了事件源为 From SpreadsheetInstallable Trigger,则 See, edit, create, and delete all your Google Sheets spreadsheets 是必需的范围如果事件类型是 On form submit,也会添加 View and manage your forms in Google Drive。这是为了让脚本能够访问由提交响应引起的电子表格中可能发生的更改。因此,它将 return 用户一个事件对象,其中包含有关导致触发器触发的上下文的信息。

如果您手动按下 运行,该脚本也可以工作,但是没有将传递给函数参数的事件对象。

您可以尝试使用 Time-driven 作为事件源,它会显示与您在 appsscript.json 中声明的范围相同的范围,因为触发器不需要访问执行触发器的电子表格。

示例:

时间驱动:

来自电子表格和打开时:

从电子表格和表单提交:

参考文献: