Free Disposable Temp Mail on Cloudflare Workers
jmail is a free, self-hosted disposable email service that runs entirely on Cloudflare Workers. No VPS, no Postfix, no Docker. It receives inbound email via Cloudflare Email Routing, stores messages in D1 (SQLite), and serves a clean web UI from the edge.
Live demo: mail.atiku.web.id
- Anonymous sessions β no sign-up, no tracking. Each browser gets its own isolated session via
localStorage. - Auto-sync 5s β messages appear automatically without manual refresh.
- Multi-domain β configure multiple mail domains (e.g.
atiku.web.id,lalekne.web.id). - Ads-ready β optional AdSense slots (header/inlist/footer) or custom HTML ad injection. Disabled by default.
- Theme customization β 5 CSS variable overrides via env vars. No code changes needed.
- Vanilla JS frontend β zero framework dependencies. Just HTML, CSS, and plain JavaScript.
- Zero dependencies beyond Hono + PostalMime β minimal supply chain.
- Runs on Cloudflare free tier β Workers, D1, Email Routing, all free.
git clone https://github.com/josskixg/jmail.git
cd jmail
npm installnpx wrangler loginEdit wrangler.toml and fill in your values. See Configuration for all variables.
npx wrangler d1 create jmail-dbCopy the database_id into your wrangler.toml, then apply the schema:
npx wrangler d1 execute jmail-db --remote --file=src/db/schema.sqlnpx wrangler deploySet up Email Routing on your domain to start receiving emails.
All environment variables are set in wrangler.toml under [vars].
| Variable | Type | Default | Description |
|---|---|---|---|
APP_NAME |
string | "jmail" |
Display name shown in the UI |
MAIL_DOMAIN |
string | "atiku.web.id" |
Comma-separated list of allowed mail domains |
WEB_HOST |
string | "mail.atiku.web.id" |
Hostname of the web frontend |
TAGLINE |
string | "Free Disposable Temporary Email & Anonymous Inbox" |
Tagline below the app name |
FOOTER_TEXT |
string | "CREATED BY JMail" |
Footer attribution text |
| Variable | Type | Default | Description |
|---|---|---|---|
META_KEYWORDS |
string | "jmail, temp mail, ..." |
Content for <meta name="keywords"> |
META_AUTHOR |
string | "JMAIL" |
Content for <meta name="author"> |
| Variable | Type | Default | Description |
|---|---|---|---|
ADS_ENABLED |
string | "false" |
Set "true" to enable ad slots |
ADS_CLIENT |
string | "" |
AdSense publisher ID (e.g. ca-pub-1234567890) |
ADS_SLOT_HEADER |
string | "" |
AdSense slot ID for header |
ADS_SLOT_INLIST |
string | "" |
AdSense slot ID between inbox rows |
ADS_SLOT_FOOTER |
string | "" |
AdSense slot ID for footer |
ADS_CUSTOM_HEADER |
string | "" |
Custom HTML/JS for header ad (overrides AdSense) |
ADS_CUSTOM_INLIST |
string | "" |
Custom HTML/JS for in-list ad (overrides AdSense) |
ADS_CUSTOM_FOOTER |
string | "" |
Custom HTML/JS for footer ad (overrides AdSense) |
Leave empty to use the default flower theme. Each value maps to a CSS custom property.
| Variable | CSS Property | Controls |
|---|---|---|
THEME_BG |
--bg-canvas |
Background color |
THEME_PRIMARY |
--pink-flower |
Primary brand color |
THEME_PRIMARY_SOFT |
--pink-soft |
Primary color lighter shade |
THEME_ACCENT |
--yellow-flower |
Accent/secondary color |
THEME_ACCENT_SOFT |
--yellow-soft |
Accent color lighter shade |
Cyberpunk:
THEME_BG = "#0a0a0f"
THEME_PRIMARY = "#ff2d95"
THEME_PRIMARY_SOFT = "#ff2d9533"
THEME_ACCENT = "#00f0ff"
THEME_ACCENT_SOFT = "#00f0ff33"Forest:
THEME_BG = "#0f1a0f"
THEME_PRIMARY = "#2d8a4e"
THEME_PRIMARY_SOFT = "#2d8a4e33"
THEME_ACCENT = "#c4a35a"
THEME_ACCENT_SOFT = "#c4a35a33"jmail/
βββ wrangler.toml
βββ package.json
βββ tsconfig.json
βββ src/
βββ index.ts # Entry point: fetch() + email() handlers
βββ config/
β βββ defaults.ts # Default config values
β βββ index.ts # Config/env loading
βββ api/
β βββ routes.ts # Hono router combining all API modules
β βββ config.ts # GET /api/config
β βββ session.ts # GET /api/session
β βββ inboxes.ts # GET/POST /api/inboxes, DELETE /api/inboxes/:address
β βββ messages.ts # GET /api/inboxes/:address/messages
β βββ system.ts # GET /api/stats, GET /api/health
β βββ helpers.ts # Shared types and middleware
βββ email/
β βββ handler.ts # PostalMime β D1 email parser
βββ db/
β βββ schema.sql # D1 table definitions
β βββ queries.ts # Typed query functions
βββ utils/
β βββ random-address.ts # Human-like random email generator
βββ web/
βββ index.html # Frontend UI
βββ styles.css # Dark theme styles
βββ docs.html # In-app API docs page
βββ icon.svg # App icon
βββ og-image.png # Open Graph preview image
βββ js/
βββ app.js # Main app logic
βββ api.js # API client wrapper
βββ config.js # Config fetching/caching
βββ inbox.js # Inbox management
βββ messages.js # Message display
βββ canvas.js # Background animation
βββ toast.js # Notification toasts
βββ ads.js # Ad slot loader
After deploying, configure Cloudflare Email Routing to receive inbound mail.
In the Cloudflare Dashboard:
- Go to Workers & Pages β select your Worker β Settings β Triggers
- Under Domains & Routes, confirm your custom domain is listed
- Go to Email β Email Routing on your domain
- Enable Email Routing (this creates the required MX and DNS records automatically)
- Go to Email β Email Routing β Routing rules
- Create a Catch-all address rule
- Set the destination to Send to a Worker β select your Worker
Add a TXT record to improve email deliverability:
| Type | Name | Content |
|---|---|---|
| TXT | @ |
v=spf1 include:_spf.mx.cloudflare.net ~all |
Send an email to any address at your domain. If routing is working, the Worker's email() handler processes it and stores it in D1.
jmail exposes a REST API at /api/ with 8 endpoints:
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/config |
Public app config (branding, ads, theme) |
GET |
/api/session |
Create or retrieve an anonymous session |
GET |
/api/inboxes |
List inboxes linked to your session |
POST |
/api/inboxes |
Create a new inbox (or claim an existing one) |
DELETE |
/api/inboxes/:address |
Remove an inbox from your session |
GET |
/api/inboxes/:address/messages |
Fetch messages for an inbox |
GET |
/api/stats |
Public stats (total inboxes, messages, domains) |
GET |
/api/health |
Health check |
Full API documentation with curl examples: API.md
| Layer | Tech |
|---|---|
| Runtime | Cloudflare Workers |
| Router | Hono |
| Email parsing | PostalMime |
| Database | Cloudflare D1 (SQLite) |
| Static hosting | Cloudflare Workers Assets (edge CDN) |
| Language | TypeScript |
| Frontend | Vanilla HTML/CSS/JS |
| Command | Description |
|---|---|
npm run deploy |
Deploy Worker + static assets |
npm run db:migrate |
Apply schema to production D1 |
npm run db:local |
Apply schema to local D1 |
npx wrangler dev |
Run Worker locally |
npx wrangler tail |
Stream live logs |
Full documentation site: josskixg.github.io/jmail
Developed by masantoid