Gmail API and IMAP
Connecting a Gmail mailbox over Google OAuth and the Gmail API gives you history-based incremental sync, labels and write-back, and tokens that refresh rather than a stored password. IMAP/SMTP works with any server at all, which is the whole point of it. Downstream, neither choice changes anything: both land in the same canonical records.
Why the choice does not reach the engine#
Mail exists twice on purpose. The tenant_* tables hold what the provider adapter fetched, in the provider's own shape; the canonical threads, messages and contacts are what the engine and every screen read, and connect_core.bridge_* copies between them. The engine never reads the provider tables.
That is why adding a provider changes nothing downstream, and why a bug in one adapter cannot corrupt a workspace's conversation history. Your connection choice is an operational decision about sync and write-back, not a decision about what Connect can do with the mail.
What each gives you#
| Gmail (OAuth + API) | IMAP/SMTP | |
|---|---|---|
| Works with | Google accounts | Any IMAP server, including self-hosted |
| Incremental sync | History-based — the provider tells you what changed | A cursor you maintain over the mailbox |
| Labels and folders | Labels are first-class; write-back can mark read and label | Folders only, and behaviour varies by server |
| Credentials | OAuth tokens that refresh; the stored config is rebuilt on every refresh | A password or app password, sealed on save and never echoed to a screen |
| Setup | A consent flow with named scopes | Host, port, TLS and credentials, once |
| Failure to plan for | A scope or consent change requiring reconnection | Cursor handling — the part that loses mail if it is done naively |
Microsoft Graph is the third supported route and behaves much more like the Gmail case than the IMAP one: an OAuth connection to a specific provider with its own richer semantics.
The cursor, which is where mail gets lost#
This is the part worth understanding whichever provider you pick. The daily allowance bounds how much mail is processed. When it is spent, work is held rather than dropped, and the read cursor deliberately does not advance — because advancing it on a refusal is how a mail agent loses messages permanently. Needs You shows the refusal so the hold is visible rather than silent.
The same principle governs an ordinary sync failure: a cursor that moves past something nobody processed has thrown mail away, and no error is raised because from the reader's point of view the mailbox is simply empty from there on. See how a mail cursor loses messages.
Health is not connection#
- **A mailbox that authenticates and returns nothing is a *quiet mailbox*** — a health signal, not an error. Both connection types can be quiet, for different reasons.
- Write-back never blocks the reply. If marking a message read or labelling it fails on Gmail, the reply still went; the two are not the same operation.
- Credentials are sealed on every save and never echoed back to a screen, for either route.
- A row with an empty workspace stamp is invisible, not missing. It matches no scope and no policy, so it silently disappears from the mailbox list while by-id actions on it still work — repair belongs to the schema owner at boot, not to a request.
Choosing#
If the mailbox is Google, connect it as Gmail.
Result You get history-based sync, labels and refreshing tokens for the same effort as typing a password.
If it is anything else — a hosting company's mail, a self-hosted server, a shared alias on an appliance — use IMAP/SMTP.
Result It works, with the same canonical result downstream.
Give each mailbox its role, signature and autonomy after connecting.
Result Those are per mailbox, not per workspace, and
ask_before_sendon one address does not slow the others down.
Questions#
Is IMAP second-class here?
No. It is a first-class provider through the same providers.build() path, and one mailbox_console runs over one policy for both audiences. What it genuinely lacks is what IMAP lacks everywhere: labels, and a provider-side history feed.
Do I need to give Google broad access?
The scopes requested are named and specific, and are listed on Gmail scopes. A change to the scope set means reconsenting — a reconnection rather than a silent upgrade.
Can I connect several mailboxes of different kinds?
Yes — several per workspace, mixed providers, each with its own role, signature, autonomy setting and health verdicts. Sending stays on the mailbox the thread belongs to rather than a global default.