Email Agent — Code Map
Folder structure
Entry points
| Entry point |
Language |
Role |
cmd/email-agent/main.go |
Go |
Service and CLI. |
internal/server/server.go |
Go |
HTTP router and middleware. |
internal/store/schema.sql |
SQL |
The AGENTS.md section 7 tables. |
CLI flags
| Flag |
Effect |
-version |
Print version, commit, and build time. |
-healthcheck |
Probe the local /health endpoint and exit. |
-fetch |
Run one Gmail IMAP scan and exit (FR-1). |
-classify |
Classify pending messages with JEV and exit. |
-classify-all |
Re-classify every stored message. |
-check-smtp |
Verify SMTP IPv4, STARTTLS, and login. Sends no mail. |
-check-thread <id> |
Confirm a stored thread has a sent reply. Read-only. |
-summary |
Build today's summary, store it, and print it. Sends nothing. |
-summary-send |
Build the summary and deliver it by email via Apprise. |
-notify |
Send one notification to the Hub (POST /notify). |
-retain |
Clear old message bodies and cap actions_log (AGENTS.md section 7). |
HTTP routes
| Method |
Path |
Auth |
Purpose |
GET |
/health |
public |
Liveness and database check. |
GET |
/readyz |
public |
Readiness. |
GET |
/login |
public |
Sign-in form. |
POST |
/login |
public |
CSRF-checked sign-in. |
POST |
/logout |
session |
End the session. |
GET |
/ |
session |
Dashboard. |
GET |
/partials/inbox |
session |
HTMX inbox fragment. |
POST |
/actions/fetch |
session + CSRF |
One IMAP scan. |
POST |
/actions/classify |
session + CSRF |
Classify pending messages. |
POST |
/actions/reclassify |
session + CSRF |
Re-classify every message. |
POST |
/actions/bulk |
session + CSRF |
Bulk delete, move, mark, restore. |
GET |
/partials/message |
session |
Message detail fragment. |
POST |
/actions/draft |
session + CSRF |
Generate and store a reply draft. |
POST |
/actions/draft/save |
session + CSRF |
Save draft edits. |
POST |
/actions/send |
session + CSRF + confirm |
Send a reply over SMTP. |
GET |
/categories |
session |
Category editor (FR-14). |
POST |
/categories/add |
session + CSRF |
Add a category. |
POST |
/categories/rename |
session + CSRF |
Rename and cascade. |
POST |
/categories/remove |
session + CSRF |
Remove and reassign. |
GET |
/rules |
session |
Rules editor (FR-11). |
POST |
/rules/save |
session + CSRF |
Save a new rules version. |
POST |
/rules/restore |
session + CSRF |
Restore an older version. |
POST |
/rules/reclassify |
session + CSRF |
Re-classify with current rules. |
GET |
/unsubscribe |
session |
Unsubscribe links and ignore list (FR-7). |
POST |
/unsubscribe/ignore |
session + CSRF |
Add a domain to the ignore list. |
POST |
/unsubscribe/unignore |
session + CSRF |
Remove a domain record. |
POST |
/unsubscribe/mark |
session + CSRF + confirm |
Record a domain. No link is followed. |
GET |
/reports |
session |
Daily summary and delete-report. |
GET |
/capabilities |
Hub bearer |
Hub capability list (FR-12). |
POST |
/ask |
Hub bearer |
Read-only short answer. |
GET |
/static/... |
public |
Embedded CSS, fonts, htmx. |
Data model
SQLite. The schema is in internal/store/schema.sql. Migrations run at start
and are recorded in schema_migrations.
| Table |
Holds |
messages |
Gmail id, thread id, headers, from, to, subject, body, source address. |
classifications |
Category, importance, action, confidence, model. |
categories |
The editable category list (FR-14). |
rules |
Plain-text rules, versioned (FR-11). |
actions_log |
Append-only action log (FR-13). Capped by -retain. |
unsubscribe |
Detected domains, status, and ignore list (FR-7). |
drafts |
Reply draft body, template, and sent state (FR-8). |
summaries |
Daily summary text and delivery target (FR-10). |
Migrations: v2 adds IMAP UID fields. v3 seeds the first categories and rules.
v4 adds folder and mailbox. v5 adds message_id_header and drafts.sent_at.
v6 adds list_unsubscribe fields and unsubscribe.url.
Key modules
| Module |
Role |
internal/mailfetch/imap.go |
Minimal IMAP client. Forces tcp4. |
internal/mailfetch/message.go |
MIME parse and the FR-2 source address. |
internal/mailfetch/imap_write.go |
IMAP MOVE, COPY, and flag changes. |
internal/classify/jev.go |
JEV /v1/systemone client. Three Choice questions. |
internal/classify/rules.go |
Rule parse and first-match-wins engine (FR-4). |
internal/mailops/mailops.go |
App folder to Gmail label mapping. |
internal/mailops/smtp.go |
SMTP send with IPv4 and STARTTLS. |
internal/reply/draft.go |
Reply prompt and OmniRoute call. |
internal/reply/templates.go |
Built-in reply templates. |
internal/store/retention.go |
Body clearing and actions_log cap. |
internal/hub/ask.go |
Deterministic, read-only answerer. |
Tests
All Go tests run in a container:
| Package |
Coverage |
internal/classify |
JEV client, rule engine, orchestration. |
internal/hub |
Answer intents, auth, read-only proof, notify. |
internal/mailfetch |
IMAP parse, MIME, FR-2, write ops. |
internal/mailops |
Label mapping, SMTP. |
internal/reply |
Draft prompts and templates. |
internal/server |
Auth, routes, CSRF, handlers. |
internal/store |
Schema, retention, triage, categories, summaries. |
internal/summary |
Counts, ordering, text. |
internal/unsubscribe |
Link detection. |
internal/apprise, internal/config, internal/session |
Client and config. |
Dependencies
Go 1.25. The only database driver is modernc.org/sqlite (pure Go, no CGO).
The mail path uses the Go standard library plus a minimal IMAP client. The UI
uses vendored HTMX and the Family Home Lab tokens.css. No JavaScript build
step.