Connect by JBRH Open Connect

Connecting an IMAP mailbox, end to end

Any IMAP and SMTP server can be connected. You supply the server settings on the connection form; Connect seals them and builds a transport from them. Reading and sending are two different connections, so they are proved separately: a sync that returns mail proves one, and a message the server acknowledges proves the other.

Status
Available What this means
Audience
both
Channels
email
In the app
#/mailboxes, #/inbox, #/needs-you
Last verified
Product version
6.3.2

The chain from credentials to first sync#

  1. Trigger — Add a mailbox on the Mailboxes screen and choose the IMAP and SMTP option rather than a hosted provider.
  2. User event — you supply the server settings your mail host documents: the hostnames, the ports, the encryption and the account.
  3. Authentication and workspace resolution — the connection form is fetched through mailbox_console.row_for, so the row it edits belongs to your workspace and no other.
  4. Ingest — the settings are sealed by settings_store on save and become the mailbox's config, which is all providers.build() reads.
  5. Canonical record — the mailbox row carries a transport, a role, a signature, its own autonomy and its own health verdicts, exactly like a hosted one.
  6. Classification — the mailbox is checked against what is already connected, so one inbox does not become two rows.
  7. Knowledge, memory and rules — the endpoint tier for this mailbox starts empty and inherits the channel and workspace tiers above it.
  8. Autonomy and approval — a new mailbox is governed by the channel rule until you set one on the endpoint itself.
  9. Action through a provider — the first sync opens IMAP, fetches from an empty cursor, and hands what it finds to the bridge.
  10. Result — canonical threads, a last-sync time, and health verdicts; the read half is now proved.
  11. Relationship, timeline and memory — senders resolve to people and companies, so a reply has history behind it from the start.
  12. Audit, usage and Needs You — the fetch is metered against the daily allowance, and a failure is queued for a person rather than retried silently for ever.

The two proofs, and why one is not enough#

IMAP reads and SMTP sends. They are different protocols, usually different hostnames, often different ports, and on some hosts different credentials entirely. A mailbox that passes one and fails the other is a real and common state, and it is the state that produces the most confusing symptom in email: conversations arrive normally and every reply fails.

ProofWhat you seeWhat changesWhat can fail
Sync returns mailThe last-sync time moves and threads appeartenant_* rows, canonical threads, then the cursorA wrong IMAP host or port, an app password the host requires, or a server refusing the connection outright
A message is acknowledgedA reply on the thread marked as sentAn outbound message with provider evidenceSMTP authentication that differs from IMAP, a submission port the network blocks, or a relay that rejects the envelope sender

Because sending happens through outbound.py — the one boundary a person and the engine share — proving the send path once proves it for both. There is no separate 'engine sending' to test afterwards.

What a half-connected mailbox looks like#

Mail arrives, replies fail
The SMTP half is wrong. The reply is not lost: it stays as a record with a failure against it, and the reply would not send says which failures retry and which need you.
Nothing arrives, sending works
The IMAP half is wrong, or the folder being read is not the one receiving mail. The mailbox row can still read as connected, which is why a last-sync time that never moves is the signal to watch.
Everything authenticates and no mail appears
A quiet mailbox — a health verdict rather than an error. It is the same shape as a mailbox nobody writes to, so check the provider's own web interface before assuming a fault.
The mailbox vanishes from the list
A row whose workspace stamp is empty matches no scope, so it is invisible on the Mailboxes screen while by-id actions on it still work. Repair runs in the boot-time migration; reconnecting on top of it would have created a second row for one inbox.

After the connection#

An IMAP mailbox behaves like any other from this point on. It is bridged into the canonical tables, so the engine never sees IMAP; it carries its own role, signature and autonomy; it is metered the same way; and its cursor obeys the same rule that a refusal never advances it. Advancing past unread work is how a mail agent loses messages permanently, and it is the one behaviour the sync path refuses to have.

Two differences are worth planning for. There is no write-back — labels and read state are a Gmail capability, not an IMAP one — and there is no history API, so advancing an IMAP cursor safely matters more here than it does on a hosted provider.

Questions#

Do I need a separate app password?

That depends on your mail host, not on Connect. Hosts that enforce two-factor authentication usually require an app-specific password for IMAP and SMTP; the host's own documentation is the authority, and the setting goes in the same sealed config as everything else.

Can one workspace mix Gmail, Microsoft Graph and IMAP mailboxes?

Yes. Providers differ only up to the bridge — the engine, the screens and the Assistant read the canonical tables, so a workspace can run one of each and nothing downstream notices which is which.

Why does the mailbox read as connected when nothing is arriving?

'Connected' is a statement about the credential, not about the mail. Health verdicts and the last-sync time are the signals that separate a working mailbox from a quiet one; see mailbox health.