Files
email_agent/docs/outline/03-code-map.md
Documenter c5760db43d docs: Phase 8 documentation - Gitea, Obsidian, Outline, Vikunja, map (AUD-74)
- README: architecture Mermaid, Phase 8 status, Phase 7 endpoints, Documentation index
- docs/outline/: AI-context collection (index, system, config, code map, runbook)
- docs/email-agent-architecture.mmd + rendered PNG + Archify map (showcase pass)
- docs/vikunja-tasks.json (Vikunja project 17, tasks 179-185)
- docs/phase8-documentation.md evidence
2026-10-13 10:46:21 +11:00

7.9 KiB

Email Agent — Code Map

Folder structure

email_agent/
├── AGENTS.md              Build spec (phases 1-8, requirements, rules).
├── README.md              Technical repository README.
├── cmd/email-agent/
│   └── main.go            Entry point. HTTP server and every CLI flag.
├── internal/
│   ├── apprise/           Apprise API client for the daily summary email.
│   ├── classify/          JEV client, rule engine, classification orchestration.
│   ├── config/            Environment-driven configuration.
│   ├── hub/               Hub contract: capabilities, /ask answerer, notify.
│   ├── mailfetch/         Stdlib-only IMAP client, MIME parse, FR-2 source address.
│   ├── mailops/           Gmail label moves, flag changes, and SMTP sending.
│   ├── reply/             OmniRoute LLM drafts and reply templates.
│   ├── server/            HTTP routes, auth middleware, HTMX handlers.
│   ├── session/           Server-side session store and signed cookie values.
│   ├── store/             SQLite open, schema, migrations, all queries.
│   ├── summary/           Deterministic daily-summary builder.
│   ├── unsubscribe/       RFC 2369/8058 and body unsubscribe-link detection.
│   └── version/           Build metadata (-ldflags).
├── web/
│   ├── embed.go           Embeds the static and template files.
│   ├── static/            tokens.css, app.css, Inter fonts, htmx.min.js.
│   └── templates/         login, dashboard, inbox, message, categories, rules,
│                          unsubscribe, reports.
├── docs/                  Phase evidence, AI context, map, diagrams.
├── Dockerfile             Multi-stage, CGO-free build.
├── docker-compose.yml     Own container, image, port, and volume.
└── Makefile               Build, test, and run targets.

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:

timeout 600 docker run --rm -v "$PWD":/src -w /src golang:1.25-alpine go test ./...
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.