Skip to main content

Gmail ExecModule

Overview

GmailModule connects ValkyrAI workflows to Gmail API v1 for messages, threads, labels, recoverable trash actions, and drafts. It exposes 13 bounded operations through the native map I/O ExecModule ABI and keeps the Google OAuth access token inside a READY IntegrationAccount.

The module always addresses the authenticated user as me, fixes the production host to https://gmail.googleapis.com/gmail/v1/users/me, caps encoded requests at 1 MiB and responses at 5 MiB, returns one provider page per execution, retries transient failures only for safe GET operations, and never automatically retries sends, label changes, trash actions, or draft mutations.

The official n8n Gmail node informed the high-value operation set: read and list messages, work with threads and labels, send mail, and manage drafts. ValkyrAI adds the IntegrationAccount security boundary, fixed-host routing, explicit bounds, response identity checks, mutation non-retry, and credential-redacted errors. This Gmail API connector does not duplicate the generic EmailModule, which is an IMAP/SMTP transport rather than a Gmail mailbox API.

Usage

  1. Enable Gmail API in the Google Cloud project that owns the OAuth client.
  2. Authorize only the scopes required by the chosen operations.
  3. Store the short-lived Google OAuth access token in the encrypted apiKey or password field of a ValkyrAI IntegrationAccount; set the account to READY.
  4. Bind that account through ExecModuleConfig.authConfig.integrationAccount.
  5. Choose one operation and provide its conditional fields.
  6. When a list returns hasMore: true, pass nextPageToken unchanged to a later execution.

The module does not refresh OAuth tokens. The account lifecycle or integration service must rotate the stored access token before it expires.

Inputs

NameTypeRequiredDescriptionConstraints
operationstringYesOperation listed below.Exact allowlist of 13 values.
resourceIdstringConditionalGmail message, thread, or draft ID.1–256 URL-safe provider-ID characters.
messageobjectConditionalEmail fields for send_message and create_draft.Non-empty, at most 8 fields, encoded request at most 1 MiB.
labelobjectConditionalLabel name and visibility for create_label.Non-empty, at most 3 allowlisted fields.
labelIdsarrayNoLabels that all listed messages or threads must have.At most 20 unique provider label IDs.
addLabelIdsarrayConditionalLabels added by modify_message.At most 100 unique IDs.
removeLabelIdsarrayConditionalLabels removed by modify_message.At most 100 unique IDs.
querystringNoGmail search-box query for message or thread lists.At most 4,096 characters; control characters rejected.
pageTokenstringNoOpaque provider continuation.1–2,048 bounded token characters; passed unchanged.
limitintegerNoProvider page size.1–500; default 100.
formatstringNoSingle message/thread representation.minimal, metadata, or full; messages also support raw; default metadata.
includeSpamTrashbooleanNoInclude SPAM and TRASH in searchable lists.Default false.

message fields:

FieldRequiredDescription
toYesOne email address, a comma-separated string, or an array; at least one recipient.
cc, bccNoAdditional recipient strings or arrays; at most 100 total recipients across all fields.
replyToNoValid reply-to email address.
subjectYesNon-empty subject, at most 512 characters with no header controls.
bodyYesPlain text or HTML body, at most 512 KiB before encoding.
bodyTypeNotext or html; default text.
threadIdNoExisting Gmail thread ID when intentionally adding a message to a thread.

The module constructs RFC 2822 MIME itself, encodes the subject and body as UTF-8, and sends the resulting message as base64url in Gmail’s raw field. Attachments, arbitrary headers, and caller-provided raw MIME are deliberately excluded from this version.

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation.
resourcestringAfter validationmessages, threads, labels, or drafts.
dataobjectSingle-resource successProvider response after a valid ID is verified.
idstringSingle-resource successVerified Gmail resource identity.
itemsarrayList successOne bounded provider page.
countintegerList successItems returned in the page.
resultSizeEstimateintegerWhen supplied by GmailProvider estimate for searchable lists.
hasMorebooleanList successWhether Gmail supplied a continuation.
nextPageTokenstringWhen another page existsOpaque token for the next execution.
httpStatusintegerProvider responseGmail HTTP status.
attemptsintegerProvider call or errorHTTP attempts consumed.
errorobjectFailureRedacted code, message, and retryable fields.

Mailbox responses are classified restricted. OAuth tokens, MIME bodies, recipients, and provider payloads are not copied into progress logs.

IntegrationAccount Requirements

SettingRequirement
ProviderGmail API v1
AuthenticationOAuth 2.0 bearer access token
StatusExactly READY
accountNameHuman-readable Google Workspace identity
apiKey or passwordEncrypted OAuth access token, 20–4,096 non-whitespace characters
RelationshipExecModuleConfig.authConfig.integrationAccount

Recommended scopes:

  • Read-only message/thread workflows: https://www.googleapis.com/auth/gmail.readonly.
  • Labels, trash, and mailbox modification: https://www.googleapis.com/auth/gmail.modify.
  • Sending and drafts: https://www.googleapis.com/auth/gmail.compose or the narrower send scope where it covers the selected action.
  • Full mailbox scope https://mail.google.com/ should be avoided unless a separately reviewed workflow truly requires it.

Google classifies several Gmail scopes as sensitive or restricted. Production OAuth verification, consent, token refresh, and domain-wide delegation remain outside this module. The fixed me path intentionally prevents caller-selected user impersonation.

Configuration

Illustrative persisted configuration:

{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:gmail-customer-success"
},
"payloadConfig": {
"parameters": "{\"operation\":\"list_messages\",\"limit\":100,\"query\":\"in:inbox is:unread\",\"labelIds\":[\"INBOX\"]}"
}
}

The relationship is symbolic. The generated IntegrationAccount record owns the encrypted OAuth token.

Operations

ResourceOperationProvider routeBehavior
Messageslist_messagesGET /messagesOne page with query, label, spam/trash, and continuation filters.
Messagesget_messageGET /messages/{id}Gets one message in the selected format.
Messagessend_messagePOST /messages/sendSends one module-built RFC 2822 message.
Messagesmodify_messagePOST /messages/{id}/modifyAdds and/or removes labels.
Messagestrash_messagePOST /messages/{id}/trashMoves one message to recoverable trash.
Messagesuntrash_messagePOST /messages/{id}/untrashRestores one message from trash.
Threadslist_threadsGET /threadsOne searchable thread page.
Threadsget_threadGET /threads/{id}Gets one thread.
Labelslist_labelsGET /labelsLists system and user labels.
Labelscreate_labelPOST /labelsCreates one user label with allowlisted visibility fields.
Draftslist_draftsGET /draftsOne draft page.
Draftscreate_draftPOST /draftsCreates one RFC 2822 draft.
Draftssend_draftPOST /drafts/sendSends one existing draft by ID.

Permanent message deletion, draft deletion/update, label deletion/update, attachments, replies that first hydrate an original message, batch mutation, mailbox history, watches/triggers, settings, filters, aliases, delegated-user access, and raw MIME passthrough are deferred.

Errors and Failure Modes

FailureCauseRetry guidance
VALIDATION_ERRORMissing or malformed field, unsafe header/recipient, unsupported label/format, invalid ID/token, or local size/page limit.Correct the request; no provider call was sent.
INTEGRATION_ACCOUNT_REQUIREDNo bound secure account.Bind the intended Google OAuth account.
INTEGRATION_ACCOUNT_NOT_READYAccount status is not READY.Refresh or repair the account before execution.
GMAIL_HTTP_400/404Provider validation, invalid Gmail query, or missing resource.Correct the request or reconcile the provider ID.
GMAIL_HTTP_401/403Expired token, disabled API, missing scope, Workspace policy, or insufficient consent.Refresh authorization and grant only the required scope.
GMAIL_HTTP_429Per-user, per-project, or quota pressure.Reads retry up to three total attempts; writes remain single-attempt.
GMAIL_HTTP_5xx / NETWORK_ERRORProvider or transport failure.Reads retry safely. Reconcile sends, label changes, trash actions, and drafts before manual retry.
RESPONSE_TOO_LARGEProvider response exceeded 5 MiB.Use metadata/minimal, narrower searches, or a smaller page.
Invalid success envelopeGmail returned no valid resource ID, the wrong ID, or a non-object response.Treat as failure and verify provider compatibility.

Errors are bounded to 500 characters and pass through credential redaction. A timed-out write may have reached Gmail, so the module refuses automatic mutation replay.

Example

Send one approved customer update:

{
"operation": "send_message",
"message": {
"to": ["buyer@example.com"],
"cc": ["account-owner@example.com"],
"replyTo": "support@example.com",
"subject": "Your account review is complete",
"body": "Your review is complete. Reply to this email if you need help.",
"bodyType": "text"
}
}

Expected normalized result:

{
"status": "success",
"operation": "send_message",
"resource": "messages",
"id": "18ca01f8b7",
"data": {
"id": "18ca01f8b7",
"threadId": "18ca01f8b7",
"labelIds": ["SENT"]
},
"httpStatus": 200,
"attempts": 1
}

Notes

  • Pagination: each execution returns at most one page. Reuse nextPageToken verbatim; no silent all-pages loop occurs.
  • Rate limits: Gmail uses per-user and per-project quotas. The module handles 429 and transient failures with at most three attempts for GET only and bounded numeric Retry-After handling.
  • API limits: provider page size is capped at 500, module requests at 1 MiB, responses at 5 MiB, search at 4,096 characters, list labels at 20, modifications at 100 labels, and outgoing recipients at 100.
  • Idempotency: reads are retry-safe. Sends, draft operations, label mutations, and trash actions are single-attempt because a timeout can leave completion ambiguous.
  • Destructive behavior: permanent deletion is not exposed. trash_message is recoverable with untrash_message; sending a draft removes the draft and creates a sent message.
  • Gmail search: query uses Gmail search-box syntax. Some searches are unavailable to tokens authorized only with the metadata scope.
  • Message bodies: this version emits a single UTF-8 plain-text or HTML MIME part. It intentionally omits attachments and arbitrary caller headers.
  • External verification: deterministic tests cover validation, fixed routing, query construction, MIME encoding, bearer authentication, pagination, retries, mutation non-retry, redaction, identity checks, and annotation discovery. Live Gmail execution is deferred until a separately authorized Google account is supplied.

See the official Gmail message resource, Gmail labels resource, Gmail drafts resource, and n8n Gmail message operations for upstream functional references.