Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MailCF

Serverless multi-user mailbox receiver di Cloudflare (receive-only), dengan frontend React dan backend Workers + D1.

Gambaran

MailCF memetakan 1 akun login ke 1 alamat inbox permanen (username@domain) dan menampilkan email masuk dari Cloudflare Email Routing.

Arsitektur (Visual)

flowchart LR
  A[Pengirim Email] --> B[Cloudflare Email Routing]
  B --> C[Cloudflare Worker Email Handler]
  C --> D[(D1 Database)]
  E[Frontend React<br/>Cloudflare Pages] --> F[Cloudflare Worker API]
  F --> D
  D --> F
  F --> E
Loading

Fitur Utama

  • Auth aman dengan PBKDF2 (WebCrypto), session token hash di D1.
  • Single inbox permanen per akun.
  • Multi-domain ready via APP_DOMAINS (aktifkan 1 atau lebih domain).
  • Ingest email via Cloudflare Email Worker (postal-mime).
  • Ownership check ketat di semua endpoint inbox/message.
  • Rate limiting untuk auth dan create inbox.
  • Viewer pesan HTML aman:
    • Sanitasi backend + frontend.
    • Render HTML email dalam iframe terisolasi agar style email tidak merusak UI app.
  • UI:
    • Inbox list/message list.
    • Copy actions + toast notification.
    • Delete per message.
    • Confirm modal untuk aksi sensitif (delete, logout).

Struktur Proyek

.
├─ frontend/                    # React + Vite + Tailwind v4
│  ├─ src/
│  │  ├─ pages/
│  │  ├─ components/
│  │  └─ lib/
│  └─ vite.config.js
├─ backend/                     # Cloudflare Worker API + Email handler
│  ├─ src/
│  │  ├─ router.js
│  │  ├─ email.js
│  │  ├─ services/
│  │  ├─ middleware/
│  │  └─ db/schema.sql
│  ├─ wrangler.toml.example
│  └─ wrangler.toml             # lokal (tidak untuk commit)
└─ package.json                 # helper script root

Stack

Layer Teknologi
Frontend React 19, React Router 7, Vite 7, Tailwind CSS 4
Backend API Cloudflare Workers, Hono
Email Parser postal-mime
Validation zod
Database Cloudflare D1 (SQLite)
Runtime JavaScript ESM (tanpa TypeScript)

Konsep Akun & Domain

  • Register/Login memakai:
    • username
    • password
    • domain (opsional jika single-domain)
  • Email akun disusun otomatis: username@domain.
  • Jika APP_DOMAINS berisi lebih dari 1 domain, UI otomatis menampilkan pilihan domain.

Endpoint API

Public

  • GET /api/health
  • GET /api/public-config
  • POST /api/auth/register body: { username, domain?, password }
  • POST /api/auth/login body: { username, domain?, password }
  • POST /api/auth/logout (idempotent, tetap clear cookie)

Auth Required

  • POST /api/auth/change-password body: { newPassword, confirmPassword }
  • GET /api/me
  • GET /api/my-inbox
  • GET /api/my-messages?limit=50&offset=0
  • GET /api/inboxes
  • GET /api/inboxes/:id
  • GET /api/inboxes/:id/messages?limit=50&offset=0
  • GET /api/messages/:id
  • DELETE /api/messages/:id

Disabled by Design (single-inbox permanen)

  • POST /api/inboxes -> 403
  • DELETE /api/inboxes/:id -> 403

Skema D1

Skema ada di backend/src/db/schema.sql, tabel:

  • users
  • sessions
  • inboxes
  • messages
  • rate_limits

Index penting:

  • idx_inboxes_user_id
  • idx_messages_inbox_received

Environment Variables

Backend

Contoh lengkap: backend/.env.example

Variable Wajib Keterangan
APP_DOMAIN Ya Domain default/fallback
APP_DOMAINS Ya Daftar domain dipisah koma
FRONTEND_ORIGIN Ya Origin frontend production
FRONTEND_ORIGIN_DEV Dev Origin frontend lokal (CORS dev)
SESSION_TTL_SECONDS Ya TTL session detik (mis. 604800)
PBKDF2_ITERATIONS Ya Iterasi hash password
INBOX_MAX_PER_USER Ya Batas inbox/user (legacy multi-inbox)
TEXT_MAX_BYTES Ya Max bytes text body email
HTML_MAX_BYTES Ya Max bytes html body email

Frontend

Contoh: frontend/.env.example

Variable Wajib Keterangan
VITE_API_BASE Ya Base API (default /api)

Konfigurasi File Penting

  • backend/wrangler.toml.example: template aman untuk commit.
  • backend/wrangler.toml: file lokal aktual (sudah di-ignore).
  • backend/.env dan frontend/.env: file lokal (sudah di-ignore).

Menjalankan Lokal

Prasyarat

  • Node.js + npm
  • Cloudflare account + Wrangler login (npx wrangler login)

1) Install dependency

npm install
npm --prefix backend install
npm --prefix frontend install

2) Setup D1

cd backend
npm run d1:create
npm run d1:migrate:local

3) Jalankan backend Worker

cd backend
npm run dev

4) Jalankan frontend

cd frontend
# optional jika worker dev bukan default
# export WORKER_DEV_URL=http://127.0.0.1:8787
npm run dev

Catatan:

  • frontend/vite.config.js sudah memproxy /api ke Worker dev (WORKER_DEV_URL atau default 127.0.0.1:8787).

Deploy ke Cloudflare

1) Backend (Workers + D1)

  1. Copy backend/wrangler.toml.example -> backend/wrangler.toml.
  2. Isi name, vars, dan binding d1_databases.
  3. Jalankan migration remote:
cd backend
npm run d1:migrate:remote
  1. Deploy worker:
cd backend
npm run deploy

2) Frontend (Pages)

  1. Build frontend:
cd frontend
npm run build
  1. Deploy ke Pages:
cd frontend
npm run deploy
  1. Pastikan domain Pages yang dipakai cocok dengan FRONTEND_ORIGIN di backend.

Setup Email Routing (Cloudflare Dashboard)

  1. Buka domain di Cloudflare Dashboard.
  2. Aktifkan Email Routing.
  3. Buat route:
    • *@your-domain.com
  4. Destination:
    • Worker mailcf-worker (atau nama worker kamu).
  5. Kirim email test ke inbox yang terdaftar.

Keamanan (Ringkas)

  • Password hash: PBKDF2-HMAC-SHA-256 + random salt.
  • Session:
    • cookie __Host-session (HttpOnly, Secure, SameSite=None, Path=/)
    • yang disimpan di DB hanya hash token.
  • CORS terbatas ke origin frontend.
  • Validasi input via zod.
  • Rate limit:
    • auth login/register per IP
    • create inbox per user
  • Sanitasi HTML email untuk cegah XSS.

UI/UX Notes

  • Tombol copy menampilkan toast sukses/gagal.
  • Konfirmasi delete message dan logout memakai modal custom (ConfirmModal).
  • Mobile action button sudah icon-first.

Script Cepat (Root)

npm run dev:backend
npm run dev:frontend
npm run build:backend
npm run build:frontend
npm run deploy:backend
npm run deploy:frontend

Troubleshooting

401 setelah login

  • Cek FRONTEND_ORIGIN dan FRONTEND_ORIGIN_DEV.
  • Pastikan request frontend credentials: include (sudah default di app).
  • Pastikan HTTPS di production.

409 saat register

  • Username sudah ada pada domain terpilih.

Email masuk tapi tidak muncul

  • Cek route Email Routing.
  • Pastikan recipient memang inbox yang ada di DB.
  • Cek logs worker (wrangler tail).

CORS error di browser

  • Samakan domain frontend dengan env backend:
    • FRONTEND_ORIGIN
    • FRONTEND_ORIGIN_DEV

Operasional

Melihat log Worker

cd backend
npx wrangler tail

Query D1 cepat

cd backend
npx wrangler d1 execute DB --remote --command "SELECT id,email,created_at FROM users ORDER BY created_at DESC LIMIT 10;"

Lisensi

Internal project / private use.

About

Serverless multi-user mailbox receiver di Cloudflare (receive-only), dengan frontend React dan backend Workers + D1.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages