Email / IMAP¶
The live email connector. If you're setting up a connector for the first time, this page is the reference — later connector pages follow the same shape.
What it does¶
A read-only, incremental IMAP poll (imaplib.IMAP4_SSL) that reads new
messages in one folder and keeps a per-folder UID cursor so each run only
fetches what's new. It reuses the same email normalization as the
mbox backfill, so live-polled and backfilled mail end up as
identical cap_items shapes.
The mailbox is opened read-only (select(folder, readonly=True)) — the
connector never deletes, moves, or marks messages.
Prereqs¶
- An IMAP account (host, port, and folder — usually
INBOX). - An app password for that account, not your regular login password.
- No host access needed — this connector runs entirely inside the container scheduler.
Env / secret_ref¶
Pick a secret_ref name (this page uses IMAP_MAIN) and set its two env
vars in .env:
JARVIS_IMAP_MAIN_USER=you@example.com
JARVIS_IMAP_MAIN_PASSWORD=your-app-password
Both are commented out in .env.example and already wired through to the
scheduler service's environment in compose.yaml — uncomment and fill them
in in your own .env, don't edit .env.example.
The cap_connectors row¶
{
"kind": "email",
"enabled": true,
"secret_ref": "IMAP_MAIN",
"config": {
"host": "imap.example.com",
"port": 993,
"ssl": true,
"folder": "INBOX"
},
"owner_addresses": ["you@example.com"]
}
owner_addresses marks which address is yours, so messages you sent are
tagged direction="out". If you leave it empty, the connector falls back to
the comma-separated JARVIS_OWNER_EMAIL env var.
Turn it on¶
- Set
JARVIS_IMAP_MAIN_USERandJARVIS_IMAP_MAIN_PASSWORDin.env. - Restart the stack so the scheduler picks up the new env vars:
./jarvis down
./jarvis up
- Create the
cap_connectorsrow above via the PocketBase admin UI — see Overview.
The scheduler's capture_agent.poll cron (every 10 minutes) picks up the new
row on its next run — no restart needed after step 3. The cursor it writes
back looks like:
{"INBOX": {"uidvalidity": 12345, "last_uid": 987}}
Verify¶
./jarvis logs scheduler
Look for a line like capture poll: {'connectors_polled': 1, 'ingested': N,
'errors': 0}. Then, in the PocketBase admin:
cap_itemsgrows by roughly the number of new messages.- The
cap_connectorsrow'slast_poll_atupdates each cron run. - The row's
last_erroris empty.
Errors¶
- Missing credentials — if either env var isn't set when the poll runs,
the row's
last_erroris set tomissing credentials (set the secret_ref env vars)and the poll skips it (other connectors keep working). - UIDVALIDITY change — if the mailbox reports a different
UIDVALIDITYthan the cursor remembers (the server rebuilt its UID space), the connector resetslast_uidto0and re-scans the whole folder from the start. This is safe:cap_itemsdedupes byexternal_id, so already-ingested messages are skipped and only genuinely new ones get written.