Agent Skills: Encode subject using RFC 2047 MIME encoding for non-ASCII characters

Gmail API for email management. Use when user says "check email", "send

UncategorizedID: vm0-ai/vm0-skills/gmail

Install this agent skill to your local

pnpm dlx add-skill https://github.com/vm0-ai/vm0-skills/tree/HEAD/gmail

Skill Files

Browse the full folder contents for gmail.

Download Skill

Loading file tree…

gmail/SKILL.md

Skill Metadata

Name
gmail
Description
Gmail API for email management. Use when user says "check email", "send

Troubleshooting

If requests fail, run zero doctor check-connector --env-name GMAIL_TOKEN or zero doctor check-connector --url https://gmail.googleapis.com/gmail/v1/users/me/profile --method GET

User Profile

Get Profile

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/profile" --header "Authorization: Bearer $GMAIL_TOKEN"

Messages

List Messages

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=10" --header "Authorization: Bearer $GMAIL_TOKEN"

List Messages with Query

Search using Gmail query syntax:

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages?q=is:unread&maxResults=10" --header "Authorization: Bearer $GMAIL_TOKEN"

Common queries:

  • is:unread - Unread messages
  • from:example@gmail.com - From specific sender
  • subject:hello - Subject contains "hello"
  • after:2024/01/01 - After date
  • has:attachment - Has attachments
  • label:INBOX - In inbox

Get Message

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}" --header "Authorization: Bearer $GMAIL_TOKEN"

Get Message (Metadata Only)

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}?format=metadata&metadataHeaders=From&metadataHeaders=Subject&metadataHeaders=Date" --header "Authorization: Bearer $GMAIL_TOKEN"

Send Email

# Encode subject using RFC 2047 MIME encoding for non-ASCII characters
ENCODED_SUBJECT="=?UTF-8?B?$(printf '%s' "{subject}" | base64 -w 0)?="

# Create RFC 2822 message and base64url encode
RAW_MESSAGE=$(printf "To: {recipient-email}\r\nSubject: ${ENCODED_SUBJECT}\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n{body-text}" | base64 -w 0 | tr '+/' '-_' | tr -d '=')

Write to /tmp/gmail_request.json:

{
  "raw": "$RAW_MESSAGE"
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Reply to Thread

# Encode subject using RFC 2047 MIME encoding for non-ASCII characters
ENCODED_SUBJECT="=?UTF-8?B?$(printf '%s' "Re: {original-subject}" | base64 -w 0)?="

# Include In-Reply-To and References headers for proper threading
RAW_MESSAGE=$(printf "To: {recipient-email}\r\nSubject: ${ENCODED_SUBJECT}\r\nIn-Reply-To: <{original-message-id}>\r\nReferences: <{original-message-id}>\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n{reply-text}" | base64 -w 0 | tr '+/' '-_' | tr -d '=')

Write to /tmp/gmail_request.json:

{
  "raw": "$RAW_MESSAGE",
  "threadId": "{thread-id}"
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/messages/send" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Modify Message Labels

Write to /tmp/gmail_request.json:

{
  "addLabelIds": ["STARRED"],
  "removeLabelIds": ["UNREAD"]
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}/modify" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Trash Message

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}/trash" --header "Authorization: Bearer $GMAIL_TOKEN"

Delete Message Permanently

curl -s -X DELETE "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}" --header "Authorization: Bearer $GMAIL_TOKEN"

Threads

List Threads

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/threads?maxResults=10" --header "Authorization: Bearer $GMAIL_TOKEN"

Get Thread

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/threads/{thread-id}" --header "Authorization: Bearer $GMAIL_TOKEN"

Trash Thread

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/threads/{thread-id}/trash" --header "Authorization: Bearer $GMAIL_TOKEN"

Labels

List Labels

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/labels" --header "Authorization: Bearer $GMAIL_TOKEN" | jq '.labels[] | {id, name, type}'

Create Label

Write to /tmp/gmail_request.json:

{
  "name": "{label-name}",
  "labelListVisibility": "labelShow",
  "messageListVisibility": "show"
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/labels" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Delete Label

curl -s -X DELETE "https://gmail.googleapis.com/gmail/v1/users/me/labels/{label-id}" --header "Authorization: Bearer $GMAIL_TOKEN"

Drafts

List Drafts

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/drafts" --header "Authorization: Bearer $GMAIL_TOKEN"

Create Draft

# Encode subject using RFC 2047 MIME encoding for non-ASCII characters
ENCODED_SUBJECT="=?UTF-8?B?$(printf '%s' "{subject}" | base64 -w 0)?="

RAW_MESSAGE=$(printf "To: {recipient-email}\r\nSubject: ${ENCODED_SUBJECT}\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n{body-text}" | base64 -w 0 | tr '+/' '-_' | tr -d '=')

Write to /tmp/gmail_request.json:

{
  "message": {
    "raw": "$RAW_MESSAGE"
  }
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/drafts" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Send Draft

Write to /tmp/gmail_request.json:

{
  "id": "{draft-id}"
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/drafts/send" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Delete Draft

curl -s -X DELETE "https://gmail.googleapis.com/gmail/v1/users/me/drafts/{draft-id}" --header "Authorization: Bearer $GMAIL_TOKEN"

Attachments

Get Attachment

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}/attachments/{attachment-id}" --header "Authorization: Bearer $GMAIL_TOKEN" | jq -r '.data' | base64 -d > attachment.bin

Settings

Get Vacation Settings

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/settings/vacation" --header "Authorization: Bearer $GMAIL_TOKEN"

Update Vacation Settings

Write to /tmp/gmail_request.json:

{
  "enableAutoReply": true,
  "responseSubject": "Out of Office",
  "responseBodyPlainText": "I am currently out of office.",
  "restrictToContacts": false,
  "restrictToDomain": false
}

Then run:

curl -s -X PUT "https://gmail.googleapis.com/gmail/v1/users/me/settings/vacation" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

List Filters

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/settings/filters" --header "Authorization: Bearer $GMAIL_TOKEN"

Create Filter

Write to /tmp/gmail_request.json:

{
  "criteria": {
    "from": "{filter-email}"
  },
  "action": {
    "addLabelIds": ["TRASH"],
    "removeLabelIds": ["INBOX"]
  }
}

Then run:

curl -s -X POST "https://gmail.googleapis.com/gmail/v1/users/me/settings/filters" --header "Authorization: Bearer $GMAIL_TOKEN" --header "Content-Type: application/json" -d @/tmp/gmail_request.json

Common Scopes

| Scope | Permission | |-------|------------| | gmail.readonly | Read-only access | | gmail.send | Send emails only | | gmail.compose | Create drafts and send | | gmail.modify | Read, send, delete, manage | | gmail.labels | Manage labels only | | gmail.settings.basic | Manage basic settings | | gmail.settings.sharing | Manage sensitive settings |

Use full URL: https://www.googleapis.com/auth/gmail.modify

Decode Message Body

Gmail returns message body as base64url encoded. To decode:

curl -s "https://gmail.googleapis.com/gmail/v1/users/me/messages/{message-id}" --header "Authorization: Bearer $GMAIL_TOKEN" | jq -r '.payload.body.data // .payload.parts[0].body.data' | tr '_-' '/+' | base64 -d

Guidelines

  1. Rate Limits: Gmail API has quota limits; implement exponential backoff
  2. Batch Requests: Use batch endpoints for multiple operations
  3. Message Format: Messages must be RFC 2822 compliant and base64url encoded

API Reference

  • REST Reference: https://developers.google.com/workspace/gmail/api/reference/rest
  • Guides: https://developers.google.com/workspace/gmail/api/guides
  • OAuth Playground: https://developers.google.com/oauthplayground/
  • Scopes: https://developers.google.com/identity/protocols/oauth2/scopes#gmail