Skip to content

Commit 7785477

Browse files
authored
fix(gmail): accept padded raw message encoding (#923)
Accept Gmail API raw payloads in both padded and unpadded base64url forms by reusing the shared decoder. Add command-level regression coverage and changelog credit. Fixes #922. Co-authored-by: goutamadwant <[email protected]>
1 parent 0ec8dbe commit 7785477

3 files changed

Lines changed: 37 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Docs: preserve external and internal text-run link targets in `docs cat --chips`, JSON, tab, table, and numbered output while keeping default text unchanged. (#917, #921) — thanks @neo-wanderer.
66
- Gmail: enforce per-account no-send guards before dry-run exits for first-class and Discovery send paths while preserving no-guard keyring avoidance. (#915, #916) — thanks @veteranbv.
7+
- Gmail: accept padded Gmail API base64url payloads in `gmail get --format raw` while retaining unpadded compatibility. (#922, #923) — thanks @goutamadwant.
78
- MCP: add optional global and per-account capability ceilings in `config.json`, with narrow persistent write authorization, runtime-only restriction, and fail-closed selector validation. (#913) — thanks @mcaldas.
89

910
## 0.34.0 - 2026-07-11

internal/cmd/gmail_get.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cmd
22

33
import (
44
"context"
5-
"encoding/base64"
65
"strings"
76

87
"github.com/steipete/gogcli/internal/gmailcontent"
@@ -127,7 +126,7 @@ func (c *GmailGetCmd) Run(ctx context.Context, flags *RootFlags) error {
127126
u.Err().Println("Empty raw message")
128127
return nil
129128
}
130-
decoded, err := base64.RawURLEncoding.DecodeString(msg.Raw)
129+
decoded, err := decodeGmailRaw(msg.Raw)
131130
if err != nil {
132131
return err
133132
}

internal/cmd/gmail_get_cmd_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,41 @@ func TestGmailGetCmd_Text_Metadata_WithAttachments(t *testing.T) {
322322
}
323323
}
324324

325+
func TestGmailGetCmd_RawAcceptsPaddedBase64URL(t *testing.T) {
326+
rawMessage := "Subject: padded\r\nContent-Type: multipart/mixed\r\n\r\nbody!"
327+
encoded := base64.URLEncoding.EncodeToString([]byte(rawMessage))
328+
if !strings.HasSuffix(encoded, "=") {
329+
t.Fatal("test fixture must include base64 padding")
330+
}
331+
332+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
333+
if !strings.Contains(r.URL.Path, "/gmail/v1/users/me/messages/") {
334+
http.NotFound(w, r)
335+
return
336+
}
337+
w.Header().Set("Content-Type", "application/json")
338+
_ = json.NewEncoder(w).Encode(map[string]any{
339+
"id": "m1",
340+
"threadId": "t1",
341+
"labelIds": []string{"INBOX"},
342+
"raw": encoded,
343+
})
344+
}))
345+
defer srv.Close()
346+
347+
result := executeWithGmailTestService(
348+
t,
349+
[]string{"--plain", "--account", "[email protected]", "gmail", "get", "m1", "--format", "raw"},
350+
newGmailServiceFromServer(t, srv),
351+
)
352+
if result.err != nil {
353+
t.Fatalf("execute: %v\nstderr=%q", result.err, result.stderr)
354+
}
355+
if !strings.Contains(result.stdout, rawMessage) {
356+
t.Fatalf("expected decoded raw message, got: %q", result.stdout)
357+
}
358+
}
359+
325360
func TestGmailGetCmd_RawEmpty(t *testing.T) {
326361
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
327362
if !strings.Contains(r.URL.Path, "/gmail/v1/users/me/messages/") {

0 commit comments

Comments
 (0)