Bug Description
The google-workspace skill's Gmail wrapper writes MIME headers with lowercase names (to, subject, cc, from) but later reads Gmail API headers with exact canonical names (To, Subject, From).
As a result, google_api.py gmail get MESSAGE_ID can report an empty to and subject for messages sent through google_api.py gmail send, even though the raw Gmail API payload contains those headers in lowercase.
Steps to Reproduce
- Use the installed
google-workspace skill on Hermes v0.15.1.
- Send a Gmail message through the wrapper:
GAPI="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/google_api.py"
$GAPI gmail send --to recipient@example.com --subject "Header test" --body "body"
- Read the returned message ID through the same wrapper:
$GAPI gmail get MESSAGE_ID
- Compare with the raw Gmail API payload or with a patched
_headers_dict() that normalizes header names case-insensitively.
Expected Behavior
gmail get should return the sent message metadata with populated fields:
{
"to": "recipient@example.com",
"subject": "Header test"
}
gmail send / gmail reply should also emit conventional RFC header names (To, Subject, Cc, From) instead of lowercase variants.
Actual Behavior
The wrapper can return:
{
"to": "",
"subject": ""
}
The message is not necessarily missing those headers. The raw Gmail API payload contains them as lowercase to / subject, while _headers_dict() stores and reads header names case-sensitively.
Affected Component
- Skills (skill loading, skill hub, skill guard)
Messaging Platform (if gateway-related)
Debug Report
N/A. This is a small code-level bug in skills/productivity/google-workspace/scripts/google_api.py, reproduced directly with the skill wrapper and confirmed by inspecting the Gmail API payload.
Operating System
Fedora Linux 43 (Sway)
Python Version
Hermes runtime: Python 3.12.13
System Python: Python 3.14.5
Hermes Version
Hermes Agent v0.15.1 (2026.5.29)
Additional Logs / Traceback (optional)
Installed skill markers on v0.15.1:
~/.hermes/skills/productivity/google-workspace/scripts/google_api.py
message["to"] present
message["To"] absent
message["subject"] present
message["Subject"] absent
Duplicate search performed before filing:
gh search issues --repo NousResearch/hermes-agent 'google workspace gmail headers lowercase' => []
gh search issues --repo NousResearch/hermes-agent 'gmail get empty subject' => []
gh search prs --repo NousResearch/hermes-agent 'google workspace gmail headers' => []
Root Cause Analysis (optional)
gmail_send() and gmail_reply() build MIME messages with lowercase header names:
message["to"] = args.to
message["subject"] = args.subject
message["cc"] = args.cc
message["from"] = args.from_header
gmail_get() then uses _headers_dict() and exact canonical lookups:
def _headers_dict(msg: dict) -> dict[str, str]:
return {h["name"]: h["value"] for h in msg.get("payload", {}).get("headers", [])}
headers.get("To", "")
headers.get("Subject", "")
Header field names are case-insensitive by RFC, but this dict access is case-sensitive.
Proposed Fix (optional)
- Emit canonical MIME header names in
gmail_send() and gmail_reply():
message["To"] = ...
message["Subject"] = ...
message["Cc"] = ...
message["From"] = ...
-
Make _headers_dict() robust by preserving original keys and also adding canonical aliases for common headers case-insensitively (from, to, cc, subject, date, message-id).
-
Add regression tests covering:
_headers_dict() normalizes lowercase Gmail API header names.
gmail_send() builds raw MIME messages with canonical To / Subject header names.
Local validation with this fix:
python -m pytest tests/skills/test_google_workspace_api.py -q -o 'addopts='
11 passed in 0.29s
python -m pytest tests/skills/test_google_workspace_api.py tests/skills/test_google_oauth_setup.py -q -o 'addopts='
26 passed in 0.47s
Bug Description
The
google-workspaceskill's Gmail wrapper writes MIME headers with lowercase names (to,subject,cc,from) but later reads Gmail API headers with exact canonical names (To,Subject,From).As a result,
google_api.py gmail get MESSAGE_IDcan report an emptytoandsubjectfor messages sent throughgoogle_api.py gmail send, even though the raw Gmail API payload contains those headers in lowercase.Steps to Reproduce
google-workspaceskill on Hermes v0.15.1.$GAPI gmail get MESSAGE_ID_headers_dict()that normalizes header names case-insensitively.Expected Behavior
gmail getshould return the sent message metadata with populated fields:{ "to": "recipient@example.com", "subject": "Header test" }gmail send/gmail replyshould also emit conventional RFC header names (To,Subject,Cc,From) instead of lowercase variants.Actual Behavior
The wrapper can return:
{ "to": "", "subject": "" }The message is not necessarily missing those headers. The raw Gmail API payload contains them as lowercase
to/subject, while_headers_dict()stores and reads header names case-sensitively.Affected Component
Messaging Platform (if gateway-related)
Debug Report
N/A. This is a small code-level bug in
skills/productivity/google-workspace/scripts/google_api.py, reproduced directly with the skill wrapper and confirmed by inspecting the Gmail API payload.Operating System
Fedora Linux 43 (Sway)
Python Version
Hermes runtime: Python 3.12.13
System Python: Python 3.14.5
Hermes Version
Hermes Agent v0.15.1 (2026.5.29)
Additional Logs / Traceback (optional)
Installed skill markers on v0.15.1:
Duplicate search performed before filing:
Root Cause Analysis (optional)
gmail_send()andgmail_reply()build MIME messages with lowercase header names:gmail_get()then uses_headers_dict()and exact canonical lookups:Header field names are case-insensitive by RFC, but this dict access is case-sensitive.
Proposed Fix (optional)
gmail_send()andgmail_reply():Make
_headers_dict()robust by preserving original keys and also adding canonical aliases for common headers case-insensitively (from,to,cc,subject,date,message-id).Add regression tests covering:
_headers_dict()normalizes lowercase Gmail API header names.gmail_send()builds raw MIME messages with canonicalTo/Subjectheader names.Local validation with this fix: