Google Sheets自定义按钮触发器中getActiveUser()运行失效
问题背景
此前可正常运行的Google Sheets绑定脚本出现异常:仅在脚本控制台手动执行时功能生效,绑定到表格内插入绘图、定时触发器的脚本调用Session.getActiveUser()时,只有表格所有者能正常获取结果,其他协作者运行时要么功能失效,要么Session.getActiveUser().getEmail()返回空字符串。所有脚本均直接在电子表格环境内运行,不属于已部署的Web应用。
测试脚本代码
function printEmail() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var s = ss.getSheetByName("Test Stuff"); var outputCell = ss.getRangeByName("testOutput"); Logger.log(Session.getActiveUser().getEmail()); outputCell.setValue( Session.getActiveUser().getEmail()); } function printAdminEmail() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var s = ss.getSheetByName("Test Stuff"); var outputCell = ss.getRangeByName("testOutput"); outputCell.setValue( Session.getEffectiveUser().getEmail()); }
异常表现
通过表格内绑定了printEmail函数的绘图按钮运行脚本时,指定输出单元格返回空值,执行结果截图如下:
当前Manifest配置
{ "timeZone": "America/New_York", "dependencies": { "enabledAdvancedServices": [ { "userSymbol": "Sheets", "version": "v4", "serviceId": "sheets" }, { "userSymbol": "DocsList", "version": "v1", "serviceId": "docs" }, { "userSymbol": "Calendar", "version": "v3", "serviceId": "calendar" }, { "userSymbol": "People", "version": "v1", "serviceId": "peopleapi" }, { "userSymbol": "Tasks", "version": "v1", "serviceId": "tasks" } ] }, "oauthScopes": [ "https://www.googleapis.com/auth/spreadsheets.readonly", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/contacts.readonly", "https://www.googleapis.com/auth/spreadsheets.currentonly", "https://www.google.com/m8/feeds", "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/calendar", "https://www.googleapis.com/auth/calendar.readonly", "https://www.google.com/calendar/feeds", "https://www.googleapis.com/auth/documents", "https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/gmail.send", "https://www.googleapis.com/auth/gmail.compose", "https://www.googleapis.com/auth/gmail.modify", "https://mail.google.com/", "https://www.googleapis.com/auth/gmail.addons.current.action.compose", "https://www.googleapis.com/auth/tasks" ], "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "sheets": { "macros": [ { "menuName": "sortCaseload", "functionName": "sortCaseload" }, { "menuName": "df", "functionName": "df" } ] }, "webapp": { "executeAs": "USER_ACCESSING", "access": "DOMAIN" } }
异常原因
该异常和业务代码逻辑无关,是Google Apps Script授权机制、Workspace安全策略、触发器固有特性共同导致的:
- 脚本通过绘图按钮、简单触发器(onEdit/onOpen等)、时间驱动触发器运行时,默认进入受限授权上下文。如果协作者所属的Google Workspace域管理员开启了用户身份信息保护策略,非表格所有者的邮箱信息会被直接屏蔽,
getEmail()方法返回空字符串。 - 虽然oauthScopes中已经配置了
https://www.googleapis.com/auth/userinfo.email权限,但通过绘图按钮触发脚本时不会主动弹出授权提示,协作者从未完成过身份相关的授权流程,接口自然拿不到有效返回值。 - 时间驱动触发器本身的运行逻辑就是以触发器创建者身份执行,不存在运行时的「当前活跃用户」概念,这个场景下拿不到其他用户邮箱属于产品固有设计,不是故障。
修复方案
根据实际使用场景选择对应方案即可:
- 优先替换触发方式:放弃绘图按钮绑定脚本的方式,改用自定义菜单触发功能。自定义菜单触发的脚本会走完整授权流程,协作者第一次点击菜单时会弹出授权窗口,完成授权后
Session.getActiveUser().getEmail()就能正常返回值。添加自定义菜单的代码如下:
function onOpen() { const ui = SpreadsheetApp.getUi(); ui.createMenu('工具菜单') .addItem('打印当前用户邮箱', 'printEmail') .addItem('打印运行身份邮箱', 'printAdminEmail') .addToUi(); }
- 如果必须保留绘图按钮的交互形式:不要用
Session.getActiveUser()取邮箱,直接调用已经启用的People高级服务,通过People.People.get('people/me', {personFields: 'emailAddresses'})接口获取当前用户邮箱,该接口在完成授权后返回值不受受限模式的邮箱屏蔽策略影响。 - 如果是企业/教育版Workspace环境:联系域管理员,在后台将该绑定脚本的ID加入域内受信任应用列表,放开用户邮箱信息的返回限制。
- 针对定时触发器场景:不需要取活跃用户,直接用
Session.getEffectiveUser().getEmail()即可拿到触发器创建者(也就是脚本实际运行身份)的邮箱,符合触发器的运行逻辑。
内容的提问来源于stack exchange,提问作者William Toscano
相关产品推荐
相关产品推荐

