Description
gws gmail +reply-all silently drops CC recipients when the original message's Cc header is stored with non-canonical casing (e.g., "CC" instead of "Cc").
Reproduction
- Have a Gmail thread where the latest message has CC recipients and the header name is
"CC" (all uppercase — common with Microsoft Exchange / Outlook)
- Run:
gws gmail +reply-all --message-id <ID> --body 'test' --draft
- Expected: Draft includes all original To + CC recipients
- Actual: Draft only includes To recipients + original sender. All CC recipients are silently dropped.
Root Cause
parse_message_headers in crates/google-workspace-cli/src/helpers/gmail/mod.rs (line 254) uses exact case-sensitive string matching:
match name {
"From" => ...
"Reply-To" => ...
"To" => ...
"Cc" => ... // ← only matches "Cc"
"Message-ID" | "Message-Id" => ... // ← already handles 2 variants
_ => {} // ← "CC" falls through silently
}
The Gmail API preserves original header casing from the sending MTA. Per RFC 5322 §1.2.2, header field names are case-insensitive, so "CC", "Cc", and "cc" are all valid.
Scope
This affects all headers in the match block, not just Cc. If any header arrives in non-canonical casing:
| Header |
Impact if missed |
From |
Hard error — function returns Err("Message is missing From header") |
Message-ID |
Hard error — Err("Message is missing Message-ID header") |
To |
+reply-all misses To recipients |
CC |
+reply-all drops CC recipients (this bug) |
Reply-To |
Reply goes to wrong recipient |
References |
Threading breaks |
Internal Inconsistency
The same file already uses case-insensitive matching in get_part_header:
fn get_part_header<'a>(part: &'a Value, name: &str) -> Option<&'a str> {
...
.find(|h| n.eq_ignore_ascii_case(name)) // ← correct approach
...
}
Suggested Fix
Normalize name before matching:
match name.to_ascii_lowercase().as_str() {
"from" => ...
"reply-to" => ...
"to" => ...
"cc" => ...
"subject" => ...
"date" => ...
"message-id" => ...
"references" => ...
_ => {}
}
This aligns with the existing get_part_header pattern and the extract_header function (which also uses eq_ignore_ascii_case).
Related
Environment
- gws 0.22.3
- macOS (arm64)
- Original message sent from Microsoft Exchange (which emits
"CC" in uppercase)
Description
gws gmail +reply-allsilently drops CC recipients when the original message'sCcheader is stored with non-canonical casing (e.g.,"CC"instead of"Cc").Reproduction
"CC"(all uppercase — common with Microsoft Exchange / Outlook)Root Cause
parse_message_headersincrates/google-workspace-cli/src/helpers/gmail/mod.rs(line 254) uses exact case-sensitive string matching:The Gmail API preserves original header casing from the sending MTA. Per RFC 5322 §1.2.2, header field names are case-insensitive, so
"CC","Cc", and"cc"are all valid.Scope
This affects all headers in the match block, not just
Cc. If any header arrives in non-canonical casing:FromErr("Message is missing From header")Message-IDErr("Message is missing Message-ID header")To+reply-allmisses To recipientsCC+reply-alldrops CC recipients (this bug)Reply-ToReferencesInternal Inconsistency
The same file already uses case-insensitive matching in
get_part_header:Suggested Fix
Normalize
namebefore matching:This aligns with the existing
get_part_headerpattern and theextract_headerfunction (which also useseq_ignore_ascii_case).Related
+reply-allimplementationparse_message_headerstopub(super)for reuse; this bug would propagateEnvironment
"CC"in uppercase)