Skip to content

feat(gmail): expose attachments in messages search JSON output #620

@obokaman-com

Description

@obokaman-com

Context

gog gmail get <id> --json exposes an attachments[] array (filename, mimeType, size, attachmentId) thanks to #83.

gog gmail messages search --include-body --json does not — even though it internally calls Gmail API with Format("full"), which returns payload.parts with all attachment metadata. The data reaches gogcli and gets dropped when building messageItem (see internal/cmd/gmail_messages.go:199-207 in v0.17.0):

type messageItem struct {
    ID       string   `json:"id"`
    ThreadID string   `json:"threadId,omitempty"`
    Date     string   `json:"date,omitempty"`
    From     string   `json:"from,omitempty"`
    Subject  string   `json:"subject,omitempty"`
    Labels   []string `json:"labels,omitempty"`
    Body     string   `json:"body,omitempty"`
}

Use case

We run a local triage engine on top of gog gmail messages search --include-body --json (bulk search → in-process matcher with rules like from:, subject:, label:…). We want to extend our matcher to support filename: / has:attachment predicates — e.g. auto-label calendar invites by detecting .ics attachments when the sender uses custom subjects (Zoom/Outlook invites that don't follow the Invitation: X (Y) Google pattern).

Gmail's own query language supports has:attachment filename:ics, and it works fine inside the query string passed to search. But once results are in our engine, the JSON doesn't carry attachment info, so we can't evaluate attachment-based predicates locally without an extra gmail get round-trip per message.

Proposal

Add an attachments[] field to messageItem in gmail messages search, populated when --include-body (or --full) is set. Same shape as the one already returned by gmail get:

\"attachments\": [
  {\"filename\": \"invite.ics\", \"mimeType\": \"text/calendar\", \"size\": 2048, \"attachmentId\": \"...\"}
]

The extraction logic already exists in fetchMessageDetails (gmail_messages.go:209-318) — it walks payload.parts to find the body. Same walk can collect parts with non-empty filename.

Alternative: dedicated flag --include-attachments if you want to keep --include-body strictly about body content.

Happy to send a PR if the direction sounds right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions