尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Briefing-first mail client — screen senders, see what needs you today. One Go binary + Postgres, FSL-1.1-MIT.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗lullmail.com — a briefing-first mail client. Mail is a document you read, not a console you operate: senders are screened once and routed forever, a daily digest tells you what actually needs you, and the work surfaces (board, calendar, notes) derive themselves from your mail instead of asking you to maintain them.
The design stance: your mail is yours. Credentials are sealed at rest, tracker images are blocked by default, and one-click export (mbox/EML, RFC 4155) is a table-stakes feature, not a cancellation flow.
g jumps, one command palette), undo on every
action, light/sepia/dark plus more palettes, no telemetry.PREFETCH_BODIES=0 to fetch bodies only when a thread is
opened.Standalone and single-owner by design: one owner per install, no multi-user tenancy, no campaign-sending infrastructure.
No configuration required:
docker compose up -d
docker compose logs app # one-time setup token, valid 24h
Open http://localhost:8080 and finish setup in the browser: paste the
token, pick a name and password (or create a passkey instead), save the
recovery codes. The token stops authenticating the moment the first
credential exists. You can sign in with that name or the account email.
Deploying with teploy instead of raw Docker? A
template teploy.yml is committed — point server: at a host from your
~/.teploy/servers.yml and teploy deploy <server>.
SECRET_KEY (seals credentials) and the setup token are generated on first
boot and kept in the appdata volume; the browser origin is detected from
your first visit and pinned — so behind a reverse proxy, reach the app
through the final public URL when you run setup. Set the env vars below only
to override any of this; env always wins. Migrations run automatically at
boot (lullmail migrate runs them by hand).
Sign-in is password-primary; passkeys, an authenticator (TOTP), and one-use recovery codes are opt-in additions, not requirements.
Retry-After); a per-host limiter throttles every
auth route. Wrong email and wrong password are indistinguishable in the
response, so accounts cannot be enumerated.lull_… Bearer) reach accounts and mail but never the
auth or security surface — that boundary is enforced in the router.| Variable | Required | Notes |
|---|---|---|
DATABASE_URL | yes | Postgres, e.g. postgres://user:pass@host:5432/lullmail |
SECRET_KEY | no | Seals mail credentials, OAuth/passkey records, TOTP, and push subscriptions with AES-256-GCM. Generated on first boot into DATA_DIR/secret.key when unset; changing it invalidates sealed data. |
LULL_TOKEN | no | One-time installation token for first-run setup (password or passkey). Generated (24h expiry, printed to logs) when unset. Rejected after the first credential exists; restart regenerates only while the install is unconfigured. |
LULL_USER_EMAIL | no | Owner address used as the internal ident. Setup collects a name (login accepts that name or this address); leave unset to derive [email protected]. |
PUBLIC_URL | no | Browser origin, e.g. https://mail.example.com. Auto-detected from the first setup visit and pinned in the database; the env var forces an origin. WebAuthn and mutation-origin checks reject a different origin. |
DATA_DIR | no | Where the generated key and setup token live (default ./data). Mount it as a volume or restarts regenerate them. |
PREFETCH_BODIES | no | 1 (default) fetches bodies of the last 30 days of mail during sync so opening recent mail is local; 0 fetches a body only when its thread is opened. |
WEBAUTHN_RP_ID | no | Relying-party domain; derived from the effective origin. |
PORT / ADDR | no | Defaults to :8080. |
Optional Google: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET. Redirect URI:
$PUBLIC_URL/api/oauth/google/callback. Required scopes are gmail.modify
and gmail.send plus identity; public multi-user distribution still requires
Google's restricted-scope verification/CASA process.
Optional Microsoft: MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, and
MICROSOFT_TENANT (default common). Redirect URI:
$PUBLIC_URL/api/oauth/microsoft/callback; delegated scopes are
User.Read, Mail.ReadWrite, Mail.Send, and offline_access.
Optional web push: VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, and
VAPID_SUBJECT (normally mailto:[email protected]). Generate a pair with any
standards-compatible VAPID tool. Notifications are deliberately generic and
never put subject/sender content on the lock screen.
Repo organization and house rules: CONVENTIONS.md.
go build ./... && go test ./... && go vet ./...
cd dashboard && npm ci && npm test && npm run typecheck && npm run build
go run . serve
dist/ is embedded into the binary at Go build time — after changing
dashboard code, rebuild the dashboard, then rebuild/restart the binary; a
running process keeps serving the copy it embedded.
The marketing site is a separate Neutron static build (site/), deployed
at lullmail.com:
cd site && npm install && npm run dev
A local mail world for testing (GreenMail — real IMAP/SMTP against fake accounts):
docker run -d --name lullmail-mail -p 127.0.0.1:10143:3143 -p 127.0.0.1:10025:3025 \
greenmail/standalone:2.0.1 -Dgreenmail.setup.test.all \
[email protected]:password
Connect [email protected] / password / host 127.0.0.1 port 10143 from
the Accounts page. Loopback IMAP is allowed plaintext for exactly this.
Mail is a great context source for scripts and AI agents, so the agent
surface is first-class: long-lived revocable Bearer tokens (fenced to mail
and work surfaces — they can never touch sign-in, passwords, passkeys, sessions, or mailbox zip export),
and a standalone MCP adapter in mcp/ that exposes the whole
read/screener/send/board/notes surface to any MCP-capable client. The
server itself stays agent-agnostic; the adapter is optional and the product
never depends on it.
One Go binary. The mail engine (mail-engine/, vendored
from Neutron's mail module) owns IMAP/JMAP sync and the mail_* mirror
tables; the product layer (this repo's Go files) owns users, sender rules,
buckets, briefing/board derivation, and the embedded Preact dashboard.
Postgres is the only dependency.
provider ──sync──> mail_* mirror ──classify──> buckets ──derive──> Today / Board / Calendar
Release-candidate, in daily production use over IMAP. Every feature above is implemented and tested locally against a real IMAP/SMTP server. Two things are operator work rather than code: the Gmail and Outlook connectors have not been exercised against real Google/Microsoft accounts (self-hosters can bring their own client IDs today; a distributed client needs Google's restricted-scope verification and CASA), and there is no hosted offering yet. Campaign-sending infrastructure is deliberately out of scope for this mailbox.
FSL-1.1-MIT (Functional Source License) — see LICENSE. Any use is
permitted except offering a competing product, and each version automatically
becomes MIT two years after its release. The copyright is held by a single
author, so a commercial/hosted license remains possible alongside the FSL;
the vendored mail-engine/ module is covered by the same license.