Connect by JBRH Open Connect

Email in Connect

Connect reads a workspace's mail through the mailboxes you connect — Gmail, a Microsoft mailbox over Graph, or any IMAP and SMTP server — copies each message into canonical records the engine reads, decides what it needs, and drafts a reply that goes out under the autonomy rule for that mailbox. Several mailboxes run at once, each with its own role, signature, autonomy and health.

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

What the channel does#

Email is the channel Connect was built around first, and it is the one where the most of the product is visible at once. A connected mailbox is fetched on a schedule; each message is canonicalised into a thread, a message and a contact; the engine triages it, grounds an answer in the workspace's knowledge and memory, and writes a reply. Whether that reply leaves the building is decided by autonomy, not by the drafting.

Everything a person does by hand goes through the same code as everything Connect does on its own. outbound.py is the single send boundary for both, which is why a message you send from the Conversations screen and a message the engine sends are recorded identically, and why proof that a message was sent means the same thing in both cases.

The channel status is available for both audiences. The Owner's workspace and a customer workspace run the same implementation; the only difference is commercial, because a customer's daily volume is bounded by their plan's allowance and the Owner has no plan.

The three providers#

ProviderHow it authenticatesWhat is distinctive
GmailGoogle OAuth, then the Gmail APIHistory-ID catch-up; label and read-state write-back
MicrosoftMicrosoft GraphGraph's own mail API and change tracking
Any IMAP/SMTP serverHost, port and credentials you supplyReads by UID; sends over your own SMTP

The adapter is chosen by the mailbox's transport, and providers.build() reads only transport and config to construct it. That narrow contract is why a fourth provider would be an adapter rather than a change to the engine, and why nothing downstream of the bridge knows which provider a message arrived through.

Mail exists twice, on purpose#

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. connect_core.bridge_* copies between them, and the engine never reads the provider tables.

Two consequences follow, and both matter more than the storage cost. Adding a provider changes nothing downstream, because the canonical shape is the only thing anything after the bridge has ever seen. And a bug in one adapter cannot corrupt a workspace's conversation history, because the adapter writes to its own table and the bridge is the only thing that promotes a row. From a provider message to a canonical one follows one message through that path.

One console, two audiences#

Mailboxes are served by one mailbox_console over one mailboxes.py policy, for the Owner and for a customer alike. The Owner's handlers were rewired onto that console rather than left as a second implementation — a second implementation is how one audience quietly acquires a capability the other lacks, which is the failure the parity suite exists to catch.

The rows still live in two tables. TenantMailbox gained the columns Mailbox always had — role, signature, autonomy and the health verdicts — and presents transport and config. Merging the tables would mean moving live customer OAuth credentials and is not required for the capability, so it has not been done.

Where the rest of this section is#

Connecting a mailbox
Mailboxes, Connecting Gmail, Connecting an IMAP and SMTP server, Connecting a Microsoft mailbox
Settings on one address
Mailbox roles, Mailbox signatures, Autonomy on one mailbox
Keeping it running
Mailbox health, A quiet mailbox, Syncing an inbox, Disconnecting a mailbox
What happens to a message
Conversation threads, Resolving a sender to a person, Triage and priority
Replying
How a reply is drafted, Held drafts, Sending email
Not sending
The suppression list, Do not contact, Unsubscribe

Everything in this section#

44 pages, each with its own status and the date it was last checked against the running system.

PageWhat it covers
A quiet mailboxA mailbox that authenticates and returns nothing: what the state means, the four ordinary reasons for it, and why it is reported as a signal rather than an error.
A send that failedA message that did not go: the failure classes, which ones are worth another attempt, what Connect completed anyway, and where the failure appears.
Approving and rejecting a draftThe two decisions on a waiting reply, what each one records, why a rejection is not a lesson, and who is accountable afterwards.
Autonomy on one mailboxGiving one address its own rule about what Connect may do: how the endpoint scope resolves against the channel and the workspace, and when it is the right tool.
Blocking a senderBlocking a sender writes a memory row tagged block:email, not a column — which is why it holds across channels and across future conversations.
BouncesWhat Connect does when a message comes back undelivered: permanent against temporary failure, which one takes an address out of use, and how a person clears it.
Connecting a Microsoft mailboxConnecting a Microsoft mailbox over Graph: what the adapter covers, the two places it differs from Gmail, and the much larger part that is identical.
Connecting an IMAP and SMTP serverConnecting a mailbox on your own mail server: the two halves of the connection, what a saved connection proves, and the ladder of checks that proves the rest.
Connecting GmailConnecting a Google mailbox: the consent path, why signing in and connecting a mailbox are different acts, and what the mailbox row holds afterwards.
Conversation threadsHow a canonical thread is formed, which signals attach a message to one, what a person's own marks on a thread control, and the ordinary ways a thread breaks.
DeliverabilityWhat Connect controls about whether mail arrives, what belongs to your own sending domain and its history, and the order worth fixing things in.
Disconnecting a mailboxRemoving a mailbox from a workspace: exactly what stops, exactly what is kept, what happens to work in flight, and the safer order to do it in.
Do not contactThe strongest entry in Connect's compliance record: what a do-not-contact instruction stops, how it is set, and why the Connect Assistant cannot lift one.
Editing a draft before it goesChanging a reply before it goes out: which fields are editable, why the sending mailbox is not, and what your edit does to the record.
Email attachmentsWhat Connect records about a document attached to an email, what it deliberately does not keep, and what a reply looks like when the enclosure was the message.
Email for the Owner and for a customerEmail runs on one implementation behind two doors. What the plan changes for a customer, what is identical, and where the asymmetry has actually gone wrong before.
Following up by emailCreating a dated commitment to write again, what is drafted when it falls due, and the reference rule that stops the same follow-up existing twice.
From a provider message to a canonical oneThe journey from a provider's own message record to the canonical thread, message and contact the engine reads — and why the engine is not allowed near the provider table.
Giving guidance on a threadThe one-line direction you give on a thread: where it is stored, how far it reaches, and when it should be a standing instruction instead.
Gmail history syncHow a Gmail mailbox resumes by history ID instead of re-reading, what a gap in that history means, and what has to happen when the provider can no longer answer.
Gmail OAuth scopes and why each is asked forThe permissions a Google mailbox connection asks for, the capability behind each one, and precisely what stops working when one is withheld or withdrawn.
Held draftsWhat happens to a reply Connect has written but is not allowed to send yet: where it waits, what the recipient sees, and how it is released.
How a reply is draftedWhat goes into a reply before a word of it is written: the thread, grounded knowledge, memory at four tiers, the rules — and the answers Connect declines to give.
IMAP UID and cursor lifecycleThe UID cursor on an IMAP mailbox: what it records, the only outcome that advances it, and the two server-side events that can invalidate it entirely.
Large batches and burstsWhat happens when hundreds of messages arrive at once: the two different orderings involved, why screen cost stays flat, and what a burst can genuinely distort.
Mailbox healthWhy a mailbox that authenticates can still be failing, what the health verdicts on the row are derived from, and which action each situation actually calls for.
Mailbox rolesWhy a mailbox carries a role, what the role changes about which address a reply leaves from and how it is written, and how to choose one deliberately.
Mailbox signaturesWhere a signature is stored, which messages it is applied to, how it interacts with a reply you have edited, and what this documentation can and cannot say about footers.
MailboxesWhat one mailbox row owns, how several run at once in a workspace, what changes when you add another, and the defect that made a connected mailbox invisible.
Outreach email versus a customer replyOutreach and a reply to a customer are two paths with different gates. What each must pass, why they are never merged, and what that costs in volume.
Proof that a message was sentWhy Connect will not call a message sent without the provider's own acknowledgement, what the third state means, and how a message in doubt is resolved.
Regenerating a draftWhen writing a reply again is the right move rather than editing it, what a fresh pass picks up, and what regenerating costs you.
Remote images in emailWhy an image in a received message loads through Connect's proxy instead of your browser, and what that changes for the sender and for you.
Rendering HTML email safelyHow Connect renders an HTML message: what the sanitiser removes, why remote images never load from the sender, and what you read instead.
Resolving a sender to a personHow an email address becomes an identity, an identity a person and a person part of a company — and what happens the first time a stranger writes to you.
Sending emailThe path an outbound message takes through Connect's single send boundary, the checks along it, and the narrow meaning the word sent may carry.
Spam complaintsWhat a spam complaint changes in Connect: escalation instead of a reply, a suppressed address at the provider, and a reputation state that can stop outreach.
Syncing an inboxHow a mailbox is read: what the first pass does that no later pass repeats, what each pass fetches, and what bounds a single pass rather than letting it run away.
The daily email allowanceWhat the daily email allowance counts, what happens when it is spent, and why the read cursor deliberately stays where it is on a refusal.
The primary mailboxWhat falls back to a workspace's default sending mailbox, how that default is expressed and changed, and what to do when a workspace appears to have none.
The suppression listThe one list checked before any outreach: what puts an address on it, what it blocks, who may take an entry off, and how it differs from blocking a person.
Triage and priorityHow a thread gets a priority, why threads.priority changes what the engine does next, and which triage marks belong to you alone.
UnsubscribeHow Connect honours an unsubscribe: the request is acted on rather than answered, a do-not-contact entry is written, and every send path checks it.
Writing back to GmailAfter Connect answers a Gmail thread it labels it and marks it read in the customer's own mailbox — and a failure to do so never blocks the reply.

Questions#

Does Connect need a new email address of its own?

No. It works the mailboxes your business already has. Replies go out from the connected address over that mailbox's own provider, so the identity your customers see is the one they already write to.

Can Connect read one mailbox and send from another?

A reply is sent from the mailbox the thread belongs to. That is decided by the mailbox's role and by the thread's own history rather than chosen per message, so a conversation that started on one address stays on it.

What happens to email that arrives while the daily allowance is spent?

It is held, not dropped, and the read cursor deliberately does not advance. Needs You shows the refusal. The mail is still on the provider and is picked up on the next pass once the allowance resets.