Skip to main content

Admin Email Integration

Overview

This document describes the complete plan for wiring real IMAP email functionality into the Admin Front-End template.
It defines architecture, backend APIs, database schema, caching policy, and the background automation system (“Reggie”).

The goals:

  • Use IMAP/SMTP only (no Gmail/Graph APIs).
  • Support multiple work accounts per user.
  • Provide manual and scheduled fetching of mail headers.
  • Avoid long-lived IMAP IDLE connections.
  • Keep data lightweight (headers only, on-demand bodies).
  • Enable Reggie — the background AI process that analyses incoming mail and drafts replies.

1. Architecture Summary

Frontend (Admin Template)
|
|-- REST API (JSON)
|
Backend (Node + Express)
|-- IMAP Client (ImapFlow)
|-- SMTP Client (Nodemailer)
|-- Job Scheduler ("Reggie" worker)
|-- Database (PostgreSQL or similar)

Connection Model

  • 1 IMAP connection per (user, account) while performing operations.
  • Connections are pooled in-memory and auto-closed after ~2-5 min idle.
  • No persistent IDLE; operations are fetch-and-close.
  • Safe auto-reconnect before every operation.

2. Front-End Behaviour

Manual “Get Mail” Button

  • Triggers authoritative resync of the top N headers (e.g. 100).
  • Adds new messages, updates flags, removes deleted ones.
  • Keeps header cache in sync with server state.

“Show More” Button

  • Fetches older pages by UID < oldestCachedUid.
  • Appends to list without trimming top.

Scheduled Fetch (Reggie)

  • Periodic (30–120 min) light fetch:
    • Only messages UID > last_seen_uid.
    • Updates header cache; doesn’t handle deletions.
  • Used for background analysis and notifications.

Cached Folders

Persistent header caches:

  • Inbox
  • Sent
  • Drafts
  • Junk
  • Trash
  • Archive

Ad-hoc Folders

Fetched on demand; purged (or expire quickly) after view closed.


3. Data Model (Database)

3.1. IMAP Accounts

CREATE TABLE email_imap_accounts (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
display_name TEXT,
email_address TEXT,
imap_host TEXT, imap_port INTEGER, imap_secure BOOLEAN,
smtp_host TEXT, smtp_port INTEGER, smtp_secure BOOLEAN,
auth_type TEXT CHECK (auth_type IN ('basic','oauth2')),
auth_json JSONB, -- encrypted credentials
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);

3.2. Mailbox State

Tracks watermarks per mailbox.

CREATE TABLE email_mailbox_state (
id SERIAL PRIMARY KEY,
account_id INTEGER REFERENCES email_imap_accounts(id),
mailbox_path TEXT,
last_seen_uid BIGINT DEFAULT 0,
oldest_cached_uid BIGINT,
updated_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(account_id, mailbox_path)
);

3.3. Cached Message Headers

Lightweight index of messages (no bodies).

CREATE TABLE email_message_headers (
id SERIAL PRIMARY KEY,
account_id INTEGER REFERENCES email_imap_accounts(id),
mailbox_path TEXT,
uid BIGINT,
msgid TEXT,
subject TEXT,
from_text TEXT,
internal_date TIMESTAMPTZ,
flags TEXT[],
has_attachments BOOLEAN,
size INTEGER,
seen BOOLEAN GENERATED ALWAYS AS (
array_position(flags, '\Seen') IS NOT NULL
) STORED,
UNIQUE(account_id, mailbox_path, uid)
);

3.4. Rules for Reggie

CREATE TABLE email_rules (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
account_id INTEGER REFERENCES email_imap_accounts(id),
mailbox_path TEXT,
rule_name TEXT,
include_senders TEXT[] DEFAULT '{}',
include_keywords TEXT[] DEFAULT '{}',
lookback_days INTEGER DEFAULT 7,
action TEXT CHECK (action IN ('draft_suggestion','label','flag'))
DEFAULT 'draft_suggestion',
is_enabled BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);

3.5. Reggie Job Ledger

CREATE TABLE email_jobs (
id SERIAL PRIMARY KEY,
user_id INTEGER,
account_id INTEGER,
mailbox_path TEXT,
uid BIGINT,
job_type TEXT CHECK (job_type IN ('analyze_and_draft')),
status TEXT CHECK (status IN ('queued','running','done','error')) DEFAULT 'queued',
error_text TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(account_id, mailbox_path, uid, job_type)
);

4. API Specification

All routes prefixed with /v1/email/imap.

Accounts

GET  /accounts
GET /accounts/:id/mailboxes

Message Listing

GET  /accounts/:id/messages?mailbox=INBOX&sinceUid=12345&limit=50
GET /accounts/:id/messages?mailbox=INBOX&olderThanUid=12000&limit=50

Response:

{
"items": [
{
"uid": 13001,
"subject": "Example subject",
"from": "Alice <alice@work.com>",
"date": "2025-10-05T01:23:45Z",
"hasAttachments": true,
"seen": false
}
],
"nextOlderThanUid": 12001,
"newestUid": 13050
}

Manual Resync (authoritative top-N)

POST /accounts/:id/mailbox/:path/resync?limit=100

Incremental Fetch (Reggie)

POST /accounts/:id/mailbox/:path/fetch-latest
Body: { "sinceUid": 12345, "limit": 200 }

Message Detail

GET /accounts/:id/messages/:uid
GET /accounts/:id/messages/:uid/attachments/:n

Flags

PATCH /accounts/:id/messages/:uid/flags
Body: { "seen": true, "flagged": false }

Send

POST /accounts/:id/send
Body: {
"to": ["person@work.com"],
"cc": [],
"bcc": [],
"subject": "Hi",
"html": "<p>Hello</p>",
"text": "Hello",
"attachments": []
}

Manual Reggie Run

POST /reggie/run
Body: { "accountId": 1, "mailbox": "INBOX", "uid": 12345, "force": true }

5. Mail Fetching Logic

Incremental (Scheduled)

  1. Read last_seen_uid.
  2. UID SEARCH UID > last_seen_uid.
  3. Fetch headers for those UIDs.
  4. Upsert into header cache.
  5. Update watermark.

Manual Resync (Authoritative)

  1. Get UIDNEXT.
  2. Determine window (UIDNEXT - 5000 : *).
  3. Fetch lightweight headers.
  4. Sort newest first, keep top N.
  5. Compare with cache: remove missing, update changed, insert new.
  6. Update watermark.

Periodic Compaction

Once per day, run resync to drop deleted messages.

Paging

Fetch olderThanUid windows for "Show More".


6. Reggie: Background AI Process

Schedule

Runs every 30–120 min per user/account; staggered.

Workflow

  1. Fetch new headers.
  2. Apply rules (senders/keywords).
  3. Fetch bodies for matches.
  4. Generate summaries & drafts.
  5. Save drafts via IMAP APPEND or DB.
  6. Record jobs and notify users.

Manual Reggie

User clicks button → analyze single message.

Safety

Rate limit, dedupe, retry, log errors.


7. Connection Lifecycle

StateBehaviour
Active fetch1 connection per (user, account)
Idle 2–5 minKeep alive; NOOP every 5–10 min
InactiveAuto-close
On next requestAuto-reconnect

8. Background Cleanup Tasks

TaskIntervalPurpose
Reggie fetch30–120 minNew mail + analysis
Light compaction24 hRemove deleted headers
Cache expiry (adhoc)30–60 minKeep DB small
Connection sweep1 minClose idle sessions

9. Security Notes

  • Encrypt all creds.
  • TLS for IMAP/SMTP.
  • Sanitize HTML.
  • Never log sensitive content.
  • Enforce per-user ownership.

10. Front-End Hooks

PageFunction
InboxFetch + render header list
DetailFetch + render body
ComposeSend via API

Toolbar

Account dropdown, folder dropdown, Reggie badge.

Buttons

ButtonEndpoint
Get MailPOST /resync
Show MoreGET /messages
ReggiePOST /reggie/run

11. Caching Policy

FolderPersistenceDescription
Inbox/Sent/Drafts etcPersistentCompacted daily
Ad-hoc foldersTemp (≤60m)Purged after view
BodiesNoneOn-demand
AttachmentsNoneStream live

12. Advantages

  • Predictable resource use.
  • Works with any IMAP server.
  • Integrates with Reggie AI pipeline.
  • Manual resync keeps state accurate.
  • Simple DB footprint.

13. Next Steps

  1. Create DB migrations.
  2. Build Express router.
  3. Implement manualResyncTopN.
  4. Wire front-end buttons.
  5. Add Reggie scheduler.
  6. Add daily compaction job.
  7. Add settings UI.
  8. Test multi-account & folders.

Document version: 2025-10-05
Prepared by ChatGPT (GPT-5) with Brett’s design notes.