Connect Gmail to automatically sync email threads into your supermemory knowledge base. Supports real-time updates via Google Cloud Pub/Sub webhooks and incremental synchronization.

**Scale Plan Required:** The Gmail connector is available on Scale and Enterprise plans only.

## Quick Setup

### 1. Create Gmail Connection

- TypeScript

```typescript
import Supermemory from 'supermemory';

const client = new Supermemory({
  apiKey: process.env.SUPERMEMORY_API_KEY!
});

const connection = await client.connections.create('gmail', {
  redirectUrl: 'https://yourapp.com/auth/gmail/callback',
  containerTags: ['user-123', 'gmail-sync'],
  documentLimit: 5000,
  metadata: {
    source: 'gmail',
    department: 'support'
  }
});

// Redirect user to Google OAuth
window.location.href = connection.authLink;
console.log('Auth expires in:', connection.expiresIn);
```

### 2. Handle OAuth Callback

After user grants permissions, Google redirects to your callback URL. The connection is automatically established and the initial sync begins.

### 3. Check Connection Status

- TypeScript

```typescript
// Get connection details
const connection = await client.connections.getByTags('gmail', {
  containerTags: ['user-123', 'gmail-sync']
});

console.log('Connected email:', connection.email);
console.log('Connection created:', connection.createdAt);

// List synced email threads
const documents = await client.documents.list({
  containerTags: ['user-123', 'gmail-sync']
});

console.log(`Synced ${documents.memories.length} email threads`);
```

## What Gets Synced

### Email Threads

Gmail threads (conversations) are synced as individual documents with all messages included:

- **Thread content** converted to structured markdown
- **All messages** within each thread preserved in order
- **Message metadata**: subject, from, to, cc, bcc, date
- **HTML content** converted to clean markdown
- **Attachment metadata**: filename, mime type, size (attachments are referenced, not stored)

### Document Metadata

Each synced thread includes searchable metadata:

| Field | Description |
| --- | --- |
| `type` | Always `gmail_thread` |
| `subject` | Email subject line |
| `threadId` | Gmail thread ID |
| `from` | Sender email address |
| `to` | Recipient email addresses |
| `date` | Date of first message |
| `messageCount` | Number of messages in thread |
| `attachmentCount` | Number of attachments (if any) |
| `attachmentNames` | List of attachment filenames |

You can filter searches using these metadata fields:

```typescript
const results = await client.search.documents({
  q: "project update",
  containerTags: ['user-123'],
  filters: JSON.stringify({
    AND: [\
      { key: "type", value: "gmail_thread", negate: false },\
      { key: "from", value: "team@company.com", negate: false }\
    ]
  })
});
```

## Connection Management

### List All Connections

- TypeScript

```typescript
// List all connections for specific container tags
const connections = await client.connections.list({
  containerTags: ['user-123']
});

connections.forEach(conn => {
  console.log(`Provider: ${conn.provider}`);
  console.log(`ID: ${conn.id}`);
  console.log(`Email: ${conn.email}`);
  console.log(`Created: ${conn.createdAt}`);
  console.log(`Document limit: ${conn.documentLimit}`);
  console.log('---');
});
```

### Delete Connection

- TypeScript

```typescript
// Delete by connection ID
const result = await client.connections.deleteByID('connection_id_123');
console.log('Deleted connection:', result.id);

// Delete by provider and container tags
const providerResult = await client.connections.deleteByProvider('gmail', {
  containerTags: ['user-123']
});
console.log('Deleted Gmail connection:', providerResult.id);
```

Deleting a connection will:

- Stop all future syncs from Gmail
- Remove the OAuth authorization
- Keep existing synced documents in supermemory (they won’t be deleted)

### Manual Sync

Trigger a manual synchronization:

- TypeScript

```typescript
// Trigger sync for Gmail connections
await client.connections.import('gmail');

// Trigger sync for specific container tags
await client.connections.import('gmail', {
  containerTags: ['user-123']
});

console.log('Manual sync initiated');
```

## Sync Mechanism

Gmail connector supports multiple sync methods:

| Feature | Behavior |
| --- | --- |
| **Real-time sync** | Via Google Cloud Pub/Sub webhooks (7-day expiry, auto-renewed) |
| **Scheduled sync** | Every 4 hours |
| **Manual sync** | On-demand via API |
| **Incremental sync** | Uses Gmail `historyId` to fetch only changed threads |

### How Real-time Sync Works

1. When a connection is created, supermemory registers a Gmail API “watch” subscription
2. Gmail sends notifications to a Google Cloud Pub/Sub topic when emails change
3. supermemory receives these notifications and fetches updated threads
4. Watch subscriptions expire after 7 days and are automatically renewed

Real-time sync monitors the **INBOX** label. Emails in other labels are synced via scheduled/manual sync.

## Permissions & Scopes

The Gmail connector requests the following OAuth scopes:

| Scope | Purpose |
| --- | --- |
| `gmail.readonly` | Read-only access to Gmail messages and threads |
| `userinfo.email` | Access to user’s email address for connection identification |

**Read-only Access:** The Gmail connector only reads emails. It cannot send, delete, or modify any emails in the user’s account.

## Limitations

**Important Limitations:**

- **Plan requirement**: Requires Scale Plan or Enterprise Plan
- **INBOX only** for real-time sync: Only INBOX label triggers real-time updates; other labels sync via scheduled sync
- **Watch expiration**: Gmail watch subscriptions expire after 7 days (automatically renewed by supermemory)
- **Document limit**: Default limit is 10,000 threads per connection (configurable via `documentLimit` parameter)
- **Attachments**: Attachment metadata is stored, but attachment content is not downloaded
- **Rate limits**: Gmail API rate limits may affect sync speed for accounts with many emails

## Troubleshooting

### OAuth Fails or Missing Refresh Token

If OAuth fails or the connection stops syncing:

1. Delete the existing connection
2. Create a new connection
3. Ensure the user completes the full OAuth flow with consent

```typescript
// Re-create connection to get fresh tokens
await client.connections.deleteByProvider('gmail', {
  containerTags: ['user-123']
});

const newConnection = await client.connections.create('gmail', {
  redirectUrl: 'https://yourapp.com/auth/gmail/callback',
  containerTags: ['user-123']
});

// User must re-authenticate
window.location.href = newConnection.authLink;
```

### Emails Not Syncing in Real-time

If real-time sync isn’t working:

- Scheduled sync (every 4 hours) and manual sync still work
- Real-time sync requires supermemory’s Pub/Sub infrastructure
- Check if the connection was created recently (watch registration happens on creation)
- Trigger a manual sync to verify the connection is working

### Permission Denied Errors

If you see permission errors:

- Ensure the user granted the required Gmail scopes during OAuth
- Verify your organization has Scale Plan or Enterprise Plan access
- Check if the user revoked app access in their Google Account settings.
