> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Mail

> Sync messages, contents and folders from an IMAP mailbox

<Warning>Mail integrations are in beta.</Warning>

`defineMailIntegration` reads an IMAP mailbox into three synced tables: one for
what the mailbox reports about each message, one for the message contents, and
one for folder membership.

```ts bijection/mailbox.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { defineMailIntegration } from "bijection/server";

export const mailbox = defineMailIntegration({ provider: "imap" });
```

```ts bijection/schema.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { defineSchema, defineTable } from "bijection/server";
import { mailbox } from "./mailbox";

export default defineSchema({
  mail_messages: defineTable(mailbox.messages.schema).source(mailbox.messages),
  mail_contents: defineTable(mailbox.contents.schema).source(mailbox.contents),
  mail_memberships: defineTable(mailbox.memberships.schema).source(
    mailbox.memberships,
  ),
});
```

`provider` is `"imap"`. `every` optionally sets the sync interval and defaults
to `{ minutes: 1 }`.

## The three collections

Every record carries a `message_key`, the message's identity. It doesn't depend
on which folders the message is in.

* **`messages`**: what the mailbox reports about a message: `provider_id`, and
  where known `thread_id`, `received_at` and `arrival_key`.
* **`contents`**: what is decoded from the message itself: `subject`,
  `message_id`, `sent_at`, the `from`, `to` and `cc` addresses, `body_text`
  and `body_html`, the raw message as a stored file in `raw_mime`, and
  `attachments`, each a stored file with its `name`, `media_type`, `size` and
  `sha256`. `content_status` is `pending`, `complete` or `unavailable`.
* **`memberships`**: which folder a message is in (`folder_key`) and its
  `flags`.

The split matters: a later pass that only reads metadata never erases contents
published earlier, and a failed content read doesn't remove the message.

`raw_mime` and each attachment's `file` are
[file storage](/file-storage/overview) IDs.

The first sync establishes the mailbox as it is. It does not report every
existing message as a new arrival.

## Connecting

The connection's private configuration names the IMAP server, the login and the
folders to read:

```json mailbox-connection.json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
{
  "kind": "imap",
  "host": "imap.example.com",
  "port": 993,
  "security": "implicit_tls",
  "username": "orders@example.com",
  "password": "…",
  "folders": ["INBOX"]
}
```

* `security` is `implicit_tls` for a TLS port, or `start_tls` to upgrade a
  plaintext connection.
* `folders` lists one to eight distinct folders.

Store it as a credential, then configure, verify and install the connection
without `--base-url`:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection integration credential-create MAILBOX --from-file mailbox-connection.json
bijection integration configure mailbox --module mailbox.js --export mailbox --credential-ref MAILBOX
bijection integration identify mailbox verify-1
bijection integration run verify-1
bijection integration install mailbox mail_messages
```

The three collections form one group: bind all three in your schema before
installing, and installing one table installs them all.

## Gaps and repair

`bijection integration source-status <source>` reports, per mailbox, how many
messages are waiting for content and how many metadata and content reads
failed. To retry the failed reads, pass the mail `revision` that
`source-status` reports:

```sh theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
bijection integration mail-repair mailbox --revision 3
```

A repair retries the missing reads without reporting the messages as new
arrivals. If the source lost continuity with the mailbox, the status says so:
a new listing can't recover every arrival from the missing interval.
