通过 gws CLI 或 Python 操作 Gmail、日历、Drive、文档
Gmail、日历、Drive、联系人、表格和文档——通过 Hermes 管理的 OAuth 和轻量 CLI 封装来操作。当安装了 gws 时,此技能将其用作后端以覆盖更多 Google Workspace 功能;否则回退到内置的 Python 客户端实现。
references/gmail-search-syntax.md — Gmail 搜索运算符(is:unread, from:, newer_than: 等)scripts/setup.py — OAuth2 设置(运行一次以授权)scripts/google_api.py — 兼容封装 CLI。优先使用 gws 执行操作,同时保留 Hermes 现有的 JSON 输出约定。设置过程完全非交互式——由你逐步引导,以便在 CLI、Telegram、Discord 或任何平台上正常工作。
先定义一个简写:
GSETUP="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/setup.py";
$GSETUP --check
如果输出 AUTHENTICATED,直接跳到"使用方式"——设置已完成。
在开始 OAuth 设置之前,向用户提出两个问题:
问题1:"您需要哪些 Google 服务?仅邮件,还是同时需要日历/Drive/表格/文档?"
himalaya 技能——它使用 Gmail 应用专用密码(设置 → 安全 → 应用专用密码)设置,仅需 2 分钟。无需 Google Cloud 项目。--services email,calendar,使同意屏幕仅请求实际需要的权限范围。--services 设置,如 calendar,drive,sheets,docs。all 服务集。问题2:"您的 Google 账号是否使用高级保护(登录时需要硬件安全密钥)?如果不确定,那大概率没有——这是需要主动注册的功能。"
告诉用户:
> 您需要创建一个 Google Cloud OAuth 客户端。这是一次性设置:
>
> 1. 创建或选择项目:
> https://console.cloud.google.com/projectselector2/home/dashboard
> 2. 从 API 库中启用所需 API:
> https://console.cloud.google.com/apis/library
> 启用:Gmail API、Google Calendar API、Google Drive API、Google Sheets API、Google Docs API、People API
> 3. 在此处创建 OAuth 客户端:
> https://console.cloud.google.com/apis/credentials
> 凭证 → 创建凭证 → OAuth 2.0 客户端 ID
> 4. 应用类型:"桌面应用" → 创建
> 5. 如果应用仍处于"测试"模式,在此处将用户的 Google 账号添加为测试用户:
> https://console.cloud.google.com/auth/audience
> 受众 → 测试用户 → 添加用户
> 6. 下载 JSON 文件并告诉我文件路径
>
> Hermes CLI 重要提示:如果文件路径以 / 开头,请勿在 CLI 中仅发送裸路径,因为它可能被误认为斜杠命令。请将它放在一个句子中使用,例如:
> JSON 文件路径为:/home/user/Downloads/client_secret_....json
一旦用户提供路径:
$GSETUP --client-secret /path/to/client_secret.json
如果用户粘贴的是原始客户端 ID / 客户端密钥值而非文件路径,请为他们写入一个有效的桌面 OAuth JSON 文件,将其保存到明确的位置(例如 ~/Downloads/hermes-google-client-secret.json),然后对该文件运行 --client-secret。
使用第1步选择的服务集。示例:
$GSETUP --auth-url --services email,calendar --format json
$GSETUP --auth-url --services calendar,drive,sheets,docs --format json
$GSETUP --auth-url --services all --format json
这将返回带有 auth_url 字段的 JSON,并将确切的 URL 同时保存到 ~/.hermes/google_oauth_last_url.txt。
此步骤的代理规则:
auth_url 字段,并将该确切的 URL 作为单行发送给用户。http://localhost:1 处失败,这是预期的。Error 403: access_denied,请直接发送 https://console.cloud.google.com/auth/audience 让他们将自己添加为测试用户。用户将粘贴回类似 http://localhost:1/?code=4/0A...&scope=... 的 URL,或仅粘贴代码字符串。两种均可。--auth-url 步骤会在本地存储一个临时的待处理 OAuth 会话,因此即使在无头系统上,--auth-code 稍后也能完成 PKCE 交换:
$GSETUP --auth-code "用户粘贴的_URL_或_代码" --format json
如果 --auth-code 因代码过期、已使用或来自较旧浏览器标签页而失败,它将现在返回一个新的 fresh_auth_url。在这种情况下,立即将新 URL 发送给用户,并让他们仅使用最新的浏览器重定向重试。
$GSETUP --check
应输出 AUTHENTICATED。设置完成——从此以后令牌将自动刷新。
~/.hermes/google_token.json,自动刷新。~/.hermes/google_oauth_pending.json,直到交换完成。gws,google_api.py 会指向同一个 ~/.hermes/google_token.json 凭证文件。用户无需运行单独的 gws auth login 流程。$GSETUP --revoke所有命令通过 API 脚本执行。将 GAPI 设置为简写:
GAPI="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/google_api.py";
# 搜索(返回 JSON 数组,含 id、from、subject、date、snippet)
$GAPI gmail search "is:unread" --max 10
$GAPI gmail search "from:boss@company.com newer_than:1d";
$GAPI gmail search "has:attachment filename:pdf newer_than:7d";
# 读取完整邮件(返回含正文的 JSON)
$GAPI gmail get MESSAGE_ID
# 发送
$GAPI gmail send --to user@example.com --subject "Hello" --body "Message text";
$GAPI gmail send --to user@example.com --subject "Report" --body "Q4
Details...
" --html
$GAPI gmail send --to user@example.com --subject "Hello" --from '"Research Agent" ' --body "Message text";
# 回复(自动关联会话并设置 In-Reply-To)
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me.";
$GAPI gmail reply MESSAGE_ID --from '"Support Bot" ' --body "Thanks";
# 标签
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID
$GAPI gmail modify MESSAGE_ID --remove-labels UNREAD
# 列出事件(默认未来 7 天)
$GAPI calendar list
$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z
# 创建事件(需要 ISO 8601 格式并带时区)
$GAPI calendar create --summary "Team Standup" --start 2026-03-01T10:00:00-06:00 --end 2026-03-01T10:30:00-06:00
$GAPI calendar create --summary "Lunch" --start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z --location "Cafe"
$GAPI calendar create --summary "Review" --start 2026-03-01T14:00:00Z --end 2026-03-01T15:00:00Z --attendees "alice@co.com,bob@co.com"
# 删除事件
$GAPI calendar delete EVENT_ID
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5
$GAPI contacts list --max 20
# 读取
$GAPI sheets get SHEET_ID "Sheet1!A1:D10";
# 写入
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[[["Name","Score"],["Alice","95"]]';
# 追加行
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[[["new","row","data"]]';
$GAPI docs get DOC_ID
所有命令返回 JSON。使用 jq 解析或直接读取。关键字段:
[{id, threadId, from, to, subject, date, snippet, labels}]{id, threadId, from, to, subject, date, labels, body}{status: "sent", id, threadId}[{id, summary, start, end, location, description, htmlLink}]{status: "created", id, summary, htmlLink}[{id, name, mimeType, modifiedTime, webViewLink}][{name, emails: [...], phones: [...]}][[cell, cell, ...], ...]setup.py --check。如果失败,引导用户完成设置。skill_view("google-workspace", file_path="references/gmail-search-syntax.md") 加载。2026-03-01T10:00:00-06:00)或 UTC(Z)。| 问题 | 修复方法 |
NOT_AUTHENTICATED | 运行上方第2-5步 |
REFRESH_FAILED | 令牌已撤销或过期——重新执行第3-5步 |
HttpError 403: Insufficient Permission | 缺少 API 范围——$GSETUP --revoke 然后重新执行第3-5步 |
HttpError 403: Access Not Configured | API 未启用——用户需在 Google Cloud Console 中启用 |
ModuleNotFoundError | 运行 $GSETUP --install-deps |
| 高级保护阻止授权 | Workspace 管理员必须允许列出 OAuth 客户端 ID |
评论区