Skip to main content
The Gmail connector lets you interact with Gmail. It uses OAuth for authentication, so you connect your Google account once and Major handles token management. For full API details, see the Gmail API documentation.

Setup

  1. Go to Organization Settings > Connectors
  2. Click Add Connector and select Gmail
  3. Choose the access scope:
    • Read only — Can list and read emails
    • Read and write — Can list, read, and send emails
  4. Choose the authentication mode:
    • Shared — Use a single shared account (the person configuring the resource provides credentials)
    • Per-user — Each app user connects their own account
  5. Click Connect to Google to authorize access
Attach the resource to your app via major resource manage (CLI) or the web editor. Major generates a client in src/clients/.

Per-User Authentication

When you configure a Gmail resource for per-user authentication, end-users authenticate with their own Google accounts instead of using shared credentials.

User Flow

  1. User accesses a deployed app that uses a per-user Gmail resource
  2. If they haven’t connected their account, Major redirects them to the /connect page
  3. User clicks Connect Gmail and authorizes access to their own email
  4. User is returned to the app and can now use Gmail features

Managing Connections

Users can view and manage their connected OAuth accounts by clicking their profile photo in the bottom left and selecting Connected Accounts. From there, they can disconnect individual OAuth credentials or reconnect if access expires. Once disconnected, users must re-authorize via the /connect page if they want to use apps that require that connection.

Usage

Import the generated client and use the helper methods:
import { gmailClient } from './clients';

Listing messages

const result = await gmailClient.gmail_list_messages(
  'list-messages',
  {
    q: 'is:unread',
    maxResults: 10
  }
);

if (result.ok) {
  const messages = result.result.messages;
  messages.forEach(msg => {
    console.log(msg.id, msg.snippet);
  });
}
Parameters:
  • operationName — A name for logging and debugging
  • options — Query options:
    • q — Search query (e.g., is:unread, from:alice@example.com, subject:important)
    • maxResults — Maximum messages to return (1–500)
    • pageToken — Token for pagination
Returns:
  • messages — Array of message objects with id, threadId, and snippet
  • nextPageToken — Token to fetch the next page of results

Getting message details

const result = await gmailClient.gmail_get_message(
  'get-message',
  {
    id: 'message-id-here',
    format: 'full'
  }
);

if (result.ok) {
  const message = result.result;
  console.log(message.payload.headers);
  console.log(message.snippet);
}
Parameters:
  • operationName — A name for logging and debugging
  • options — Query options:
    • id — Message ID (required)
    • format — Response format: minimal, full, or raw
Returns:
  • id — Message ID
  • threadId — Thread ID
  • payload — Message payload with headers and body
  • snippet — Preview of message content

Sending messages

const result = await gmailClient.gmail_send_message(
  'send-message',
  {
    to: 'recipient@example.com',
    subject: 'Hello',
    body: 'This is the email body'
  }
);

if (result.ok) {
  console.log('Email sent:', result.result.id);
}
Parameters:
  • operationName — A name for logging and debugging
  • messageBody — Message object with:
    • to — Recipient email address (required)
    • subject — Email subject (required)
    • body — Email body (required)
    • cc — CC recipient(s)
    • bcc — BCC recipient(s)
Returns:
  • id — The sent message’s ID
  • threadId — Thread ID
  • Full message object with all details

Low-level API

For operations not covered by helper methods, use invoke() directly:
const result = await gmailClient.gmail_invoke(
  'GET',
  '/users/me/messages',
  'list-messages',
  {
    query: { q: 'is:unread', maxResults: 10 }
  }
);

Supported API paths

MethodPathDescription
GET/users/me/messagesList messages
GET/users/me/messages/{id}Get message details
POST/users/me/messages/sendSend message
POST/users/me/messages/{id}/modifyModify message
DELETE/users/me/messages/{id}Delete message
GET/users/me/threadsList threads
GET/users/me/threads/{id}Get thread details
User ID is typically me to reference the authenticated user’s mailbox.

Error handling

import { ResourceInvokeError } from '@major-tech/resource-client';

try {
  const result = await gmailClient.gmail_list_messages(
    'list-messages',
    { q: 'is:unread' }
  );

  if (!result.ok) {
    // Resource returned an error (e.g., invalid query)
    console.error('Gmail error:', result.error.message);
    return;
  }

  // Success
  console.log(result.result.messages);

} catch (e) {
  if (e instanceof ResourceInvokeError) {
    // Client-level error (e.g., OAuth not completed)
    console.error('Invocation error:', e.message);
  }
}

Common errors

ErrorCause
401 UnauthorizedOAuth not completed—reconnect the resource
403 ForbiddenWrite operation on a read-only resource
400 Bad RequestInvalid query or message data
404 Not FoundMessage or thread not found

Scope and permissions

When creating the resource, you choose between:
  • Read onlyGET requests only
  • Read and write — Full read/write access including sending messages
The scope is enforced at the API level. If you try to send an email with a read-only resource, you’ll get a 403 error.
Major uses the most restrictive Google OAuth scope, which only grants access to the user’s mailbox—not additional Google services.