# Repairing a broken mailbox, end to end

A broken mailbox is repaired in place: you reconnect the row that already exists rather than adding a new one, which keeps its role, its signature, its autonomy and its history. Detection comes from health verdicts and a last-sync time that has stopped moving, and the repair is only finished once a sync and a send have both been proved again.

- **Status:** Available
- **Audience:** both
- **Channels:** email
- **In the app:** #/mailboxes, #/needs-you, #/inbox
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/workflows/mailbox-repair/

## The repair, stage by stage

1. Trigger — a health verdict turns, a Needs You entry appears, or somebody notices replies have stopped arriving.
2. User or external event — usually something outside Connect: a revoked grant, a rotated password, a mail host that changed a setting.
3. Authentication and workspace resolution — every action on the row goes through `mailbox_console.row_for`, so a mailbox id from a browser can only reach a mailbox in your own workspace.
4. Ingest — the diagnosis reads the row's verdicts, its last-sync time and its recent failures rather than asking the provider again first.
5. Canonical record — the existing mailbox row is the thing being repaired; nothing new is created, because a second row for one inbox is worse than a broken one.
6. Classification — which half is broken: reading, sending, or the credential behind both.
7. Knowledge, memory and rules — the endpoint tier stays attached to the row, so a repaired mailbox keeps every rule set against it.
8. Autonomy and approval — the mailbox's own autonomy is untouched by a reconnection; a mailbox that was holding replies still holds them afterwards.
9. Action through a provider — re-consent at Google, or replace the sealed server settings for an IMAP mailbox.
10. Result — `oauth.store_tokens` rebuilds `config` and assigns it back; the row is the same row with a working credential.
11. Relationship, timeline and memory — nothing was detached while the mailbox was down, so threads, people and companies pick up where they stopped.
12. Audit, usage and Needs You — the reconnection is recorded, and the Needs You entry drains by itself once its cause has cleared.

## Finding which half broke

A mailbox has two working halves and one credential, and the symptom tells you which is at fault before you touch anything.

| Stage | What you see | What changes | What can fail |
|---|---|---|---|
| Detection | A health verdict, or a last-sync time frozen hours ago | Nothing yet | Trusting a green row: 'connected' describes the credential, not the mail |
| Reading broken | No new conversations; sending still works | Nothing arrives in `tenant_*` | A revoked grant, an expired token, or a changed IMAP setting |
| Sending broken | Conversations arrive; replies fail or stay uncertain | Failed outbound records against the thread | SMTP credentials that differ from the reading ones, or a relay refusing the sender |
| Both broken | Nothing moves in either direction | Nothing | The credential itself — a rotated password or a revoked consent |
| Nothing broken | Authentication succeeds and no mail arrives | Health records a quiet mailbox | Assuming a fault where the honest answer is that nobody has written |

> **Note** A mailbox that has disappeared from the Mailboxes screen is a different fault from one that is failing. A row whose workspace stamp is empty matches no scope and no policy, so it is invisible to every list while every by-id action on it still works. That repair belongs to the boot-time migration as the schema owner — writing the stamp from a request is refused by the policy, which would turn a missing row into an error page.

## Reconnect the row, never add a second

The instinct when a mailbox stops working is to connect it again from scratch. Resist it. A second row for one real inbox means two cursors over the same mail, two health verdicts, two sets of autonomy, and replies that go out under whichever row the thread happened to attach to.

That failure used to be reachable: when a row carried an empty workspace stamp, the uniqueness check could not see it, so connecting the same identity again wrote a duplicate with no warning at all. The list and the uniqueness check now both ask the one query that can see such rows, read-only, which means a reconnection finds the existing mailbox even when a screen cannot show it.

1. Open the existing mailbox row rather than Add a mailbox.
   - Result: The reconnection updates `config` on the row you already have.
2. For Google, run the consent again; for IMAP, replace the server settings.
   - Result: The credential is resealed on save and never echoed back to the form.
3. Press Sync and watch the last-sync time move.
   - Result: The reading half is proved.
4. Send or approve one reply from that mailbox.
   - Result: The sending half is proved, with the provider's acknowledgement on the message.
5. Check that the Needs You entry has gone.
   - Result: Entries drain themselves as their cause clears; one that stays means the cause has not.

## What a repair does not fix

- Mail that arrived while the mailbox was down is fetched on the next sync, because the cursor never advanced past unprocessed work. What was missed is delay, not loss.
- Replies that failed while sending was broken stay as failed records against their threads. They are re-sent by a person, deliberately, rather than replayed automatically.
- A reply whose state was left *uncertain* is not resolved by reconnecting; it is resolved by looking at the provider's own sent folder, as [the send result is uncertain](/docs/troubleshooting/uncertain-send/) describes.
- A workspace left with no primary mailbox needs the role assigning, which is a separate flow: [repairing a workspace with no primary mailbox](/docs/workflows/primary-mailbox-repair/).

## Questions

### Will reconnecting lose my conversation history?

No. History lives in the canonical `threads` and `messages`, which are not touched by a credential change. Reconnecting replaces the mailbox's stored grant or server settings and nothing else.

### Do I have to set the role and signature again?

No. Role, signature, autonomy and health verdicts belong to the mailbox row, and the row survives the repair. That is the main practical reason to reconnect in place rather than start again.

### How do I know the repair held rather than worked once?

Watch the last-sync time over the following ticks rather than the moment after you reconnect. A grant that authenticates once and fails to refresh looks identical to a healthy one for exactly as long as the first access token lasts.

## Related

- [Disconnecting a mailbox](https://connectbyjbrh.com/docs/email/mailbox-disconnect/)
- [Mailbox health](https://connectbyjbrh.com/docs/email/mailbox-health/)
- [The mailbox disconnected](https://connectbyjbrh.com/docs/troubleshooting/mailbox-disconnected/)
- [Reconnect required](https://connectbyjbrh.com/docs/troubleshooting/reconnect-required/)
- [Repairing a workspace with no primary mailbox](https://connectbyjbrh.com/docs/workflows/primary-mailbox-repair/)
- [Why 'connected' is not enough to prove mailbox health](https://connectbyjbrh.com/research/mailbox-health-beyond-connected/)
- [A row with no workspace stamp is invisible, not missing](https://connectbyjbrh.com/research/invisible-not-missing/)

## What this page is based on

- Connect source pack — channels, §1: health versus connected, the three mailbox defects, `row_for` (`docs-source/sources/CHANNELS.md`)
- Connect source pack — architecture: boot-time migrations and workspace scoping (`docs-source/sources/GENERAL.md`)
- Connect capability registry (`docs-source/facts.py`) — `mailbox_health`, `gmail_oauth`, `imap_smtp`
