name: provider-adapter-design description: Apply when adding, changing, or reviewing provider behavior across Gmail (Gmail API), Office 365 (Microsoft Graph), or IMAP/SMTP. Keeps provider-specific protocol details behind src/server/mail/adapters/types.ts MailProviderAdapter. Triggers on edits to src/server/mail/adapters/, src/server/auth/oauth.ts, src/app/api/connect/, src/app/api/mail/.
provider-adapter-design
Source of truth: specs/email-adapters.md.
When to invoke
- A cooperation plan mentions adding a provider, changing list/get/send/reply/forward/archive/delete/applyLabel behavior, or normalizing protocol concepts.
- An adapter-shaped test fails.
- Reviewer or test-runner finds protocol detail leaking into an API route.
Contract invariants
MailProviderAdapter(insrc/server/mail/adapters/types.ts) is the single boundary.- API routes in
src/app/api/mail/*never import provider SDKs. They usesrc/server/mail/provider-registry.ts. - Provider concepts normalize to the app model:
- Gmail labels →
MailLabel[]. - Microsoft categories + folder →
MailLabel[]. - IMAP folder + flags →
MailLabel[].
- Gmail labels →
- Send paths use
src/server/mail/mime.tsfor MIME assembly. Gmail uses base64url; Microsoft uses Graph payload; IMAP uses nodemailer SMTP. - OAuth refresh tokens and IMAP passwords pass through
src/server/security/crypto.tsAES-256-GCM. Never logged in cleartext.
Checklist
- New methods land on the
MailProviderAdapterinterface first. - All three implementations (gmail.ts, microsoft.ts, imap.ts) updated or explicitly skipped with justification.
-
src/server/mail/adapters/normalization.test.tsupdated. - Demo mailbox in
src/lib/demo-data.tsstill produces sane output for the change. - No SDK import outside
src/server/mail/adapters/*.
Anti-patterns
- API route doing protocol-specific work in a
switch (provider)block. - Provider-specific field bleeding into
EmailMessageinsrc/lib/types.ts. - Send paths skipping the MIME helper.
- Credentials stored in plaintext anywhere.