Receive-only email management panel built with Next.js and deployed on Cloudflare Workers via OpenNext.
Live site: email.siputzx.my.id
Mailku is a private admin panel for managing receive-only mailboxes. Inbound emails are processed by a Cloudflare Worker, with metadata stored in D1 and raw emails/attachments stored in R2.
custom-worker.ts— Cloudflare Worker entry point handling both HTTP requests (Next.js app) and inbound email (POST /email)- Next.js (OpenNext) — Admin dashboard UI and API routes
- D1 Database — Mailbox, email, attachment metadata, and admin security state
- R2 Bucket — Raw email storage (
raw/*.eml) and attachments (attachments/*) - TOTP Authentication — Admin login secured with Google Authenticator + rate-limited session management
| Layer | Technology |
|---|---|
| Framework | Next.js 15 (React 19) |
| Runtime | Cloudflare Workers (via OpenNext) |
| Database | Cloudflare D1 (SQLite) |
| Storage | Cloudflare R2 |
| Email Parsing | PostalMIME |
| Auth | TOTP (Google Authenticator) + session cookies |
- Node.js 20+
- Cloudflare account with D1 and R2 provisioned
- Wrangler CLI authenticated
npm installSet these as Worker secrets:
wrangler secret put ADMIN_TOTP_SECRET
wrangler secret put ADMIN_SESSION_SECRET| Variable | Description |
|---|---|
ADMIN_TOTP_SECRET |
Base32 secret for Google Authenticator |
ADMIN_SESSION_SECRET |
Random string for session cookie signing |
npm run db:migrate:local # Apply to local D1
npm run db:migrate:remote # Apply to remote D1npm run dev # Next.js dev server
npm run build:cf # Build OpenNext worker artifact
npm run preview # Preview worker locallynpm run deploy- Admin API endpoints require a valid session cookie
- TOTP login enforced with lockout and rate limiting (D1-backed)
- Session HMAC-signed with per-request rotation
- Rate limiter: 10 login attempts per 60 seconds per IP
MIT