Gmail Trigger (Push + History) Overview - Gmail Trigger is a Dify provider that receives Gmail push notifications via Cloud Pub/Sub and emits concrete events based on Gmail History: - `gmail_message_added` (new messages) - `gmail_message_deleted` (deleted messages) - `gmail_label_added` (labels added to messages) - `gmail_label_removed` (labels removed from messages) - Dispatch verifies/auths the push, pulls the history delta once, and splits changes for events to consume. - Note: API Key is NOT supported for Gmail API access. Use OAuth (gmail.readonly) only. Prerequisites - A Google account authorized for Gmail API (used during OAuth) - A Google Cloud project with Pub/Sub API enabled (configured at tenant-level by administrator) Step-by-step Setup 1. Install the plugin in Dify - Options: - If packaged as `.difypkg`, import it in Dify’s Plugin Center (Plugins → Import). - For local run during development, ensure the runtime installs dependencies in `requirements.txt`. 2. Configure GCP resources (Administrator, one-time setup) - Create or select the Google Cloud project that will host your Pub/Sub resources. Make sure the following APIs are enabled _(APIs & Services → Library)_: - Gmail API: https://console.cloud.google.com/apis/library/gmail.googleapis.com - Cloud Pub/Sub API: https://console.cloud.google.com/apis/library/pubsub.googleapis.com - Create a dedicated service account and grant Pub/Sub permissions: 1. Go to IAM & Admin → Service Accounts → **Create Service Account**. Console URL: https://console.cloud.google.com/iam-admin/serviceaccounts Screenshot: [![GCP Service Account](./_assets/GCP_SERVICE_ACCOUNT.png)](./_assets/GCP_SERVICE_ACCOUNT.png) 2. Assign the `roles/pubsub.admin` role to this service account or select "Pub/Sub Admin" role which already includes the necessary permissions (required so the plugin can create topics, subscriptions, and update IAM policies automatically). - Alternatively, a custom role must include: `pubsub.topics.create`, `pubsub.topics.getIamPolicy`, `pubsub.topics.setIamPolicy`, `pubsub.subscriptions.create`, `pubsub.subscriptions.get`, `pubsub.subscriptions.delete`, `pubsub.subscriptions.list`. Screenshot: [![GCP Permissions](./_assets/GCP_PERMISSION.png)](./_assets/GCP_PERMISSION.png) 3. Create a JSON key for this service account and download it securely. Screenshot: [![GCP Key](./_assets/GCP_KEY.png)](./_assets/GCP_KEY.png) - Note your Google Cloud **Project ID** (displayed on the project dashboard or IAM page). 3. Configure OAuth client for the plugin (Administrator, one-time setup) - In Google Cloud Console → APIs & Services → Credentials → **Create Credentials** → OAuth client ID. Console URL: https://console.cloud.google.com/apis/credentials Screenshot: [![GCP OAuth Client](./_assets/GC_OAUTH_CLIENT.png)](./_assets/GC_OAUTH_CLIENT.png) - Application type: **Web application** - Authorized redirect URIs: copy the redirect URI shown in Dify when you set up the plugin (e.g., `https:///console/api/plugin/oauth/callback`) - Capture the generated **Client ID** and **Client Secret** for later use. 4. Enter OAuth client parameters in Dify - In the plugin configuration form: - `client_id`: The OAuth client ID created above. - `client_secret`: The corresponding client secret. - `gcp_project_id`: The Google Cloud project ID with Pub/Sub enabled. - `gcp_service_account_json`: Paste the full JSON key created for the service account (keep it private). - Dify will automatically derive a per-user Pub/Sub topic when the end user authorizes the plugin. 5. User: Authorize and create subscription - Click "Authorize" to complete OAuth (gmail.readonly scope) - Create a Gmail subscription with optional parameters: - `label_ids` (optional): Scope to specific labels (INBOX, UNREAD, etc.) - Docs: https://developers.google.com/gmail/api/reference/rest/v1/users.labels/list - Properties (optional, for enhanced security): - `require_oidc`: Enforce OIDC bearer verification - `oidc_audience`: Webhook endpoint URL (auto-filled) - `oidc_service_account_email`: Service account used for Push subscription What happens automatically: - Plugin creates/reuses a Pub/Sub Topic in your GCP project - Plugin grants Gmail API publisher permission to the topic - Plugin creates a dedicated Push subscription for this user - Plugin calls Gmail `users.watch` API to start monitoring - On unsubscribe, plugin cleans up the Push subscription (topic is preserved for reuse) Where To Get OIDC Values - `oidc_audience` - Use the exact webhook endpoint URL shown in the Dify subscription details (Endpoint). Example: - `https:///api/plugin/triggers/` - The YAML field includes a URL to Google docs for the `audience` claim: see the OIDC token reference. - `oidc_service_account_email` - The service account used by the Pub/Sub push subscription (set via `--push-auth-service-account`). - Find it under Google Cloud Console → IAM & Admin → Service Accounts, or via: - `gcloud iam service-accounts list --format='value(email)'` - The YAML field links to the Service Accounts console page. How It Works - Dispatch (trigger) - Optionally verifies OIDC bearer from Pub/Sub push (iss/aud/email) - Decodes `message.data` to get `historyId`/`emailAddress` - Calls `users.history.list(startHistoryId=...)` once to gather deltas - Splits changes per family and stores pending batches in Dify storage - Returns the list of concrete event names for Dify to execute - Events - Read the pending batch for their family - `gmail_message_added` fetches full message metadata (headers, attachments meta) - Output matches the event YAML `output_schema` Event Outputs (high-level) - `gmail_message_added` - `history_id`: string - `messages[]`: id, threadId, internalDate, snippet, sizeEstimate, labelIds, headers{From,To,Subject,Date,Message-Id}, has_attachments, attachments[] - `gmail_message_deleted` - `history_id`: string - `messages[]`: id, threadId - `gmail_label_added` / `gmail_label_removed` - `history_id`: string - `changes[]`: id, threadId, labelIds Attachment Handling - The trigger attempts to upload at most 20 real attachments (with `attachmentId` or inline content), skipping individual files larger than 5 MiB. - `attachments[].file_url` is the only externally exposed download address; `attachments[].file_source` identifies its origin (`gmail` for original links or `dify_storage` for Dify mirror). - When attachments are successfully uploaded to Dify, both `upload_file_id` and `original_url` (Gmail/Drive original address) are returned; if not mirrored, `original_url` is omitted. - Gmail often returns Drive links for oversized attachments, or provides sharing addresses directly in the message body. The event scans text/HTML content to extract these links and returns them as attachment items for unified handling by callers. - Callers only need to use `file_url`, determining whether to access Gmail/Drive directly or go through Dify storage based on `file_source`. Lifecycle & Refresh - Create: Plugin auto-provisions Pub/Sub, then calls `users.watch` with `topicName` and optional `labelIds` - Refresh: `users.watch` is called again before expiry (Gmail watch is time-limited, ~7 days) - Delete: Calls `users.stop` and cleans up the Push subscription Testing - Send an email to the watched mailbox (INBOX). You should see `gmail_message_added` - Mark read/unread (UNREAD label removed/added) triggers label events - Delete an email triggers `gmail_message_deleted` - Tip: You can view recent deliveries in Pub/Sub subscription details; Dify logs/console will show trigger and event traces. Troubleshooting - Plugin fails to create subscription: Check GCP credentials are correctly configured in OAuth client parameters - Nothing triggers: Verify Gmail API and Pub/Sub API are enabled in your GCP project - 401/403 at dispatch: OIDC settings mismatch; verify service account and audience - `historyId` out of date: Plugin resets checkpoint to the latest notification and skips the batch - OAuth issues: Re-authorize; ensure gmail.readonly scope is granted References - Gmail Push: https://developers.google.com/workspace/gmail/api/guides/push - History: https://developers.google.com/gmail/api/reference/rest/v1/users.history/list - Messages: https://developers.google.com/gmail/api/reference/rest/v1/users.messages/get