You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅拥有ClientEmail、Key和CalendarEmail,如何用Google Apps Script访问谷歌日历?

问题解答

一、CalendarEmail就是日历ID

谷歌日历的ID本身就是对应邮箱地址——不管是个人主日历(比如xxx@gmail.com)还是共享日历(比如xxx@group.calendar.google.com),这个邮箱地址就是合法的日历ID。你之前用CalendarApp.getCalendarById(CalendarEmail)返回null,根本原因是当前脚本用的是执行者个人账号的权限,而不是你手里的服务账号权限,所以没权限访问目标日历。

二、用现有信息完全能连接日历,OAuth2报错是私钥格式问题

你手里的ClientEmail(服务账号邮箱)、Key(服务账号私钥)、CalendarEmail(目标日历ID)足够完成访问,不需要额外信息。OAuth2报Exception: Invalid argument: key是因为私钥格式不对,按下面步骤修正:

1. 修正私钥格式

服务账号的私钥必须是完整的PEM格式,要包含首尾标记和正确换行,比如:

const privateKey = `-----BEGIN PRIVATE KEY-----
你的2200字符密钥内容(要保留原有的换行,别把所有内容挤成一行)
-----END PRIVATE KEY-----`;

如果你的key是从JSON密钥文件里复制的,注意把转义的\n换成实际换行,或者直接用模板字符串包裹原内容。

2. 正确配置OAuth2服务

调整后的OAuth2代码示例:

function getCalendarService() {
  const CLIENT_EMAIL = "你的服务账号邮箱";
  const PRIVATE_KEY = `-----BEGIN PRIVATE KEY-----
你的完整私钥内容
-----END PRIVATE KEY-----`;
  const CALENDAR_EMAIL = "目标日历邮箱(也就是日历ID)";
  const SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]; // 只读权限够的话用这个,更安全

  return OAuth2.createService("CalendarService")
    .setTokenUrl("https://oauth2.googleapis.com/token") // 新版API用这个URL更可靠
    .setPrivateKey(PRIVATE_KEY)
    .setIssuer(CLIENT_EMAIL)
    .setSubject(CALENDAR_EMAIL) // 模拟访问该日历的身份
    .setScope(SCOPES);
}

3. 给服务账号开日历访问权限

  • 打开目标日历的设置页面,找到「共享权限」,添加你的服务账号邮箱(ClientEmail),给它「查看所有事件」或更高权限。
  • 这步必须做,不然服务账号根本没权限碰这个日历。

4. 调用API获取事件并写入表格

授权完成后,就可以用OAuth2的token调用Calendar API拿事件,再写到电子表格里:

function fetchCalendarEvents() {
  const service = getCalendarService();
  if (!service.hasAccess()) {
    throw new Error("服务账号没权限:" + service.getLastError());
  }

  // 设置时间范围
  const startDate = new Date("2024-01-01");
  const endDate = new Date("2024-12-31");
  const calendarId = encodeURIComponent("你的目标日历邮箱");
  const url = `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events?timeMin=${encodeURIComponent(startDate.toISOString())}&timeMax=${encodeURIComponent(endDate.toISOString())}`;
  
  const response = UrlFetchApp.fetch(url, {
    headers: {
      Authorization: "Bearer " + service.getAccessToken()
    }
  });

  const events = JSON.parse(response.getContentText());
  // 把事件写到电子表格
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.clearContents();
  sheet.appendRow(["标题", "开始时间", "结束时间"]);
  events.items.forEach(event => {
    sheet.appendRow([
      event.summary || "无标题",
      event.start.dateTime || event.start.date,
      event.end.dateTime || event.end.date
    ]);
  });
}

三、总结

  • 不需要额外的日历ID,CalendarEmail就是有效的日历ID。
  • 之前CalendarApp调用失败是因为权限不匹配,必须用服务账号的OAuth2权限访问。
  • OAuth2报错的核心是私钥格式错误,修正格式+给服务账号开日历权限后,就能正常获取事件。

内容的提问来源于stack exchange,提问作者Dan Muntean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:52:39