# Email Provider Adapters – Developer Guide This document explains how provider-specific adapters (e.g. `GmailAdapter`, `MicrosoftAdapter`) are structured and what **NOT** to do after the Pub/Sub refactor. ## Responsibilities | Layer | Responsibilities | Must **not** | |-------|------------------|--------------| | Adapter (`GmailAdapter.ts`) | • Refresh & cache OAuth tokens
• Fetch / send messages
• Register or renew **Gmail watch** only | Create / modify Pub/Sub topics or subscriptions | | Orchestrator (`configureGmailProvider.ts`) | • One-time call to `setupPubSub`
• Calculate standard topic / subscription names
• Call `GmailAdapter.registerWebhookSubscription()` | Talk directly to Gmail API for message operations | ## Adding / Modifying an Adapter 1. **Implement Base Methods** – extend `BaseEmailAdapter` and provide `connect`, `getMessage`, `sendMessage`, etc. 2. **Implement `registerWebhookSubscription`** * For Gmail this calls `gmail.users.watch()`. * For Microsoft this calls the Graph `subscriptions` endpoint. * Do *not* touch Google Pub/Sub or Azure EventGrid – the orchestrator handles infrastructure. 3. **Persist any IDs / expiration** into `_email_provider_config`. ### Example: GmailAdapter.registerWebhookSubscription ```ts async registerWebhookSubscription() { await this.ensureValidToken(); const { project_id, pubsub_topic_name } = this.config.provider_config; const topic = `projects/${project_id}/topics/${pubsub_topic_name}`; await this.gmail.users.watch({ userId: 'me', requestBody: { topicName: topic, labelIds: ['INBOX'] } }); // Save historyId & expiration … } ``` ## Testing See `development/testing.md` for unit and E2E recipes. The most important unit test is that **no adapter** invokes `setupPubSub`.