gogcli 草稿列表指南:gog gmail drafts list 命令的完整用法与分页原理
2026/9/17 4:16:29 网站建设 项目流程

gogcli 草稿列表指南:gog gmail drafts list 命令的完整用法与分页原理

【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli

导读

gog gmail drafts list是 gogcli(Google Workspace in your terminal)中用于列出 Gmail 草稿的核心只读命令。本文以 docs/commands/gog-gmail-drafts-list.md 为主线,系统讲解该命令的调用形式、全部可用标志(Flag)及其含义,并结合 gmail_drafts.go 与 paged_list_helpers.go 等源码,深入剖析分页抓取、--max/--limit数量限制、JSON 输出结构以及--fail-empty非零退出码的底层实现。读完本文,你将能在终端中熟练列出、筛选与脚本化消费 Gmail 草稿列表。

说明:该命令的文档页面由gog schema --json自动生成,仓库中标注“Do not edit this page by hand; runmake docs-commands”,因此本文所有参数均与 internal/cmd/gmail_drafts.go 中的命令结构体定义保持一致。

命令概览:从父命令到子命令

gog gmail drafts list位于gmail → drafts → list的命令层级中,其父命令为 gog gmail drafts,该父命令同时管理草稿的 create / get / delete / send / update / reply / reply-all / forward 等操作。在源码中,父命令定义为:

type GmailDraftsCmd struct { List GmailDraftsListCmd `cmd:"" name:"list" aliases:"ls" help:"List drafts"` Get GmailDraftsGetCmd `cmd:"" name:"get" aliases:"info,show" help:"Get draft details"` Delete GmailDraftsDeleteCmd `cmd:"" name:"delete" aliases:"rm,del,remove" help:"Permanently delete a draft (not recoverable; drafts are not moved to Trash)"` Send GmailDraftsSendCmd `cmd:"" name:"send" aliases:"post" help:"Send a draft"` Create GmailDraftsCreateCmd `cmd:"" name:"create" aliases:"add,new" help:"Create a draft"` Update GmailDraftsUpdateCmd `cmd:"" name:"update" aliases:"edit,set" help:"Update a draft"` Reply GmailDraftsReplyCmd `cmd:"" name:"reply" help:"Save a reply as a draft"` ReplyAll GmailDraftsReplyAllCmd `cmd:"" name:"reply-all" aliases:"replyall" help:"Save a reply-all as a draft"` Forward GmailDraftsForwardCmd `cmd:"" name:"forward" aliases:"fwd" help:"Save a forward as a draft"` }

list子命令本身还提供别名ls,因此以下三种写法等价:

gog gmail drafts list gog gmail drafts ls gog gmail ls

同时,顶层还允许把gmail简写为mailemail、把drafts简写为draft。完整的规范用法如下:

gog gmail (mail,email) drafts (draft) list (ls) [flags]

命令专属标志:控制返回数量、分页与空结果行为

gog gmail drafts父命令共享的全局标志不同,list子命令在源码 gmail_drafts.go 中只声明了四个专属标志:

标志类型默认值说明
--max
--limit
int6420每页最大结果数
--page
--cursor
string分页游标(page token),用于翻页
--all
--all-pages
--allpages
boolfalse自动抓取全部页面直到结束
--fail-empty
--non-empty
--require-results
boolfalse无结果时以退出码 3 结束

下面逐个深入讲解其实现与使用要点。

--max / --limit:单页返回上限,必须大于 0

--max(别名--limit)默认值为20,决定每次向 Gmail API 请求的maxResultsRun方法在一开始就会调用校验函数:

if err := validateGmailMaxResults(c.Max); err != nil { return err }

该校验定义在 gmail_search_request.go:

func validateGmailMaxResults(maxResults int64) error { if maxResults <= 0 { return usage("--max must be > 0") } return nil }

因此--max 0或负数会被直接拒绝并给出--max must be > 0的错误信息。增大该值可减少分页往返次数,但 Gmail API 本身对单次列表请求也有上限约束,实际使用时建议根据草稿规模在 20~500 之间权衡。注意:--max只控制单页大小,若要一次性取回全部草稿,应配合下面的--all使用。

--page / --cursor:手动分页游标

--page(别名--cursor)用于从指定页码游标继续拉取。源码中会把非空的 page token 透传给 Gmail API:

fetch := func(pageToken string) ([]*gmail.Draft, string, error) { call := svc.Users.Drafts.List("me").MaxResults(c.Max).Context(ctx) if strings.TrimSpace(pageToken) != "" { call = call.PageToken(pageToken) } resp, callErr := call.Do() ... }

也就是说,命令内部通过Users.Drafts.List("me")调用 Gmail API,使用固定的"me"作为用户标识,即以当前登录账号为准。第一次调用无需携带--page;每页返回的nextPageToken可在文本输出中看到提示(见下文“分页与空结果提示”),将其填入--page即可继续获取下一页。

--all / --all-pages:自动抓取全部分页

--all(别名--all-pages--allpages)会把分页逻辑交给统一的 loadPagedItems:

func loadPagedItemsT any ([]T, string, error) { if all { items, err := collectAllPages(page, fetch) ... } return fetch(page) }

collectAllPages进一步调用 collectPages,其行为要点包括:

  • 循环调用fetch,直到返回的nextPageToken为空;
  • 内置pageTokenGuard去重保护,防止分页循环导致死循环;
  • 单次调用最多抓取10_000页作为兜底上限(collectAllPages传入maxPages=10_000)。

因此--all适合脚本化地一次性导出全部草稿 ID,例如:

gog gmail drafts list --all --json

--fail-empty:无结果时退出码为 3

--fail-empty(别名--non-empty--require-results)用于 CI 与脚本中判断“是否没有任何草稿”。其实现位于 paging.go:

const emptyResultsExitCode = 3 func failEmptyExit(failEmpty bool) error { if !failEmpty { return nil } return &ExitError{Code: emptyResultsExitCode, Err: nil} }

当列表为空且设置了该标志时,命令以退出码3结束;0表示成功,非 0表示出错或条件未满足,因此3为“结果为空”保留了语义化的独立退出码,方便上层脚本区分“命令执行失败”与“没有数据”两种情形。

共享的全局标志:身份、输出与安全

list命令继承父命令gog gmail drafts的全部全局标志。除上表列出的四个专属标志外,实际执行时最常配合使用的是以下几组:

账号与认证相关

标志类型默认值说明
-a
--account
--acct
string账号邮箱、别名或auto(用于已认证的 Google API 命令)
--clientstringOAuth 客户端名称(选择已存储的凭据与 token 桶)
--access-tokenstring直接使用提供的 access token(绕过已存储的 refresh token;token 约 1 小时过期)
--quota-projectstring用于计费的 Google Cloud 项目(作为X-Goog-User-Project请求头;部分 API 在使用--access-token或 ADC 时必需)

多账号场景下,--account a@b.com可以精确指定要列出哪个账号的草稿;也可以使用别名。若未指定,则按配置选择默认账号。

输出格式相关

标志类型默认值说明
-j
--json
--machine
boolfalse以 JSON 输出到 stdout(最适合脚本化处理)
-p
--plain
--tsv
boolfalse以稳定的可解析纯文本输出到 stdout(TSV,无颜色)
--results-onlyboolJSON 模式下只输出主要结果(丢弃nextPageToken等信封字段)
--select
--pick
--project
stringJSON 模式下按逗号分隔选择字段(尽力而为,支持点路径;多数命令推荐改用--fields
--colorstringauto颜色输出策略:auto/always/never

安全与交互相关

标志类型默认值说明
--readonlyboolfalse运行时拦截所有变更类 API 请求;auth add也只会请求只读 OAuth 作用域
--gmail-no-sendboolfalse阻断 Gmail 发送类操作(Agent 安全开关)
-n
--dry-run
--noop
--preview
bool不执行变更,只打印将要执行的动作并成功退出
-y
--force
--assume-yes
bool跳过破坏性命令的确认提示
--no-input
--non-interactive
bool永不提示,直接失败(适合 CI)
--wrap-untrustedboolfalse在 JSON/raw 输出中,为抓取到的文本字段包裹外部不可信内容标记

由于list本身是只读命令,--dry-run--readonly对其影响较小,但同一父命令下的deletesend等操作会严格受-y/--force--readonly--gmail-no-send约束。另有--disable-commands--enable-commands--enable-commands-exact(以点路径限定命令白名单)、--home(覆盖 gogcli 的 config/data/state/cache 根目录,等价于GOG_HOME)、-v/--verbose--version-h/--help等通用标志,完整列表见 gog-gmail-drafts-list.md。

输出解析:表格输出、JSON 结构与空结果提示

默认文本输出:ID 与 MESSAGE_ID 两列

非 JSON 模式下,命令通过outfmt.WriteTable输出表格,列定义位于 gmail_presentation.go:

func gmailDraftColumns() []outfmt.Column[*gmail.Draft] { return []outfmt.Column[*gmail.Draft]{ {Header: "ID", Value: func(draft *gmail.Draft) string { return draft.Id }}, {Header: "MESSAGE_ID", Value: func(draft *gmail.Draft) string { if draft.Message == nil { return "" } return draft.Message.Id }}, } }

即默认表格包含ID(草稿 ID)与MESSAGE_ID(对应消息 ID,无消息时为空)两列。compactGmailRows会先过滤掉响应中的空指针条目(见 gmail_presentation.go),避免 nil 行导致渲染异常。

JSON 输出:drafts 数组 + 信封字段

--json后,输出结构定义在 gmail_drafts.go:

type item struct { ID string `json:"id"` MessageID string `json:"messageId,omitempty"` ThreadID string `json:"threadId,omitempty"` }

每条草稿被整理为idmessageId(可选)、threadId(可选)三个字段,整体包裹在信封对象中:

{ "drafts": [ { "id": "r123456789", "messageId": "18abc...", "threadId": "18abc..." } ], "nextPageToken": "0..." }

nextPageToken即为翻页游标;若配合--results-only,该信封字段会被丢弃,只输出drafts主体,方便下游直接消费。测试用例 execute_gmail_more_commands_test.go 中即以--json --account a@b.com gmail drafts list的形式对列表、get、create、update、send、delete 等草稿全链路进行了端到端验证。

分页与空结果提示

  • 若当前页仍有下一页,命令会通过printNextPageHintWithAll打印提示,告知可继续使用--page <token>翻页或改用--all/--all-pages一次抓全(见 output_helpers.go);
  • 当列表为空且未指定--fail-empty时,文本模式会在 stderr 打印No drafts并正常退出(退出码 0);指定--fail-empty后则以退出码3结束;
  • JSON 模式下空结果同样通过writePagedJSONResult输出信封(drafts为空数组),并根据--fail-empty决定是否以退出码 3 结束(见 paged_list_helpers.go)。

实战示例

列出当前账号前 20 条草稿:

gog gmail drafts list

列出草稿并输出为 JSON(便于 jq 处理):

gog gmail drafts list --json

指定账号与单页数量:

gog gmail drafts list --account me@example.com --max 50

一次性抓取全部草稿 ID:

gog gmail drafts list --all --json --results-only

在 CI 脚本中判断“是否有草稿”(无结果时退出码为 3):

gog gmail drafts list --fail-empty --json

延伸阅读

  • 父命令与同层级子命令:gog gmail drafts(create / get / delete / send / update / reply / reply-all / forward)
  • Gmail 系列命令入口:gog gmail
  • 全部命令索引:Command index
  • 核心实现:internal/cmd/gmail_drafts.go(GmailDraftsListCmd定义于 L31-L36,Run方法于 L38-L102)
  • 分页基础设施:internal/cmd/paged_list_helpers.go 与 internal/cmd/paging.go(--all全量抓取、--fail-empty退出码 3、页游标去重保护)
  • 输出列定义:internal/cmd/gmail_presentation.go
  • 数量校验:internal/cmd/gmail_search_request.go

【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询