【问题标题】:Limiting OAuth scope for Google App Script限制 Google App Script 的 OAuth 范围
【发布时间】:2021-11-08 16:09:43
【问题描述】:

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

如果我让脚本完全访问工作表和表单,它会按预期运行。我只是想减少一些权限。屏幕截图显示,它要求的权限超出了 appsscript.json 文件中指定的权限。

此脚本附加到从我的表单生成的响应表中。

来自我的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 表单/表格问题/列

  • 时间戳

  • 发件人姓名

  • 收件人姓名

  • 收件人老板的姓名

  • 大喊

  • 收件人电子邮件

  • 收件人的老板电子邮件

OAuth 权限截图:

项目详情 OAuth 范围:

【问题讨论】:

  • 那么你的问题是什么?
  • 我不希望脚本“查看、编辑、创建和删除您的所有 Google 表格电子表格”或“查看和管理您在 Google 云端硬盘中的表单”。我希望脚本只能访问此特定工作表及其响应。
  • 截图地址。您可以在删除敏感信息(如客户端 ID、客户端密码)后将其粘贴到此处吗?
  • @RayFranosa 该信息在编辑历史记录中仍然可见。如果您想完全删除,请“标记”您的问题和包含敏感信息的答案以供“主持人干预”并解释。相关:meta.stackoverflow.com/questions/327142

标签: google-apps-script google-oauth


【解决方案1】:

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

如果您手动按运行,脚本也将起作用,但没有将传递给函数参数的事件对象。

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

示例:

时间驱动:

来自电子表格和打开时:

来自电子表格和表单提交:

参考资料:

【讨论】:

  • 就是这样。我没有注意到这些触发器所需权限的差异。谢谢。
【解决方案2】:

我相信你的目标如下。

  • 根据您的问题,您想限制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 Service的GmailApp.sendEmail时,范围是恒定的https://mail.google.com/。这似乎是当前的规范。因此,当您想限制范围时,我认为您可以使用 Gmail API 来实现。当您的脚本使用 Gmail API 转换后,它变为如下。

修改脚本:

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

/**
 * @OnlyCurrentDoc
 */

// This is from https://stackoverflow.com/a/66088350
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。请注意这一点。

  • 例如,当您想使用其他方法时,请为其添加范围。我的回答是为您在问题中显示脚本。请注意这一点。

参考:

【讨论】:

  • @RayFranosa 现在我理解了您的编辑。很抱歉我没有注意到它。
猜你喜欢
  • 2016-07-01
  • 2014-09-16
  • 2016-04-30
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 2021-08-08
相关资源
最近更新 更多