Source & license
Upstream license: MIT
License TL;DR
You can use it, change it, self-host it and sell it. Keep the original copyright and license notice with copies of the code. You don’t have to publish your changes. The authors don’t promise it will work.
Explain MIT in plain English →Summary of the main license. Separate packages and assets can have different terms.
Inspect repository ↗Read this project’s actual license ↗Repository owner
See the upstream repository for the original creator and contributors.
Maintain this project? Maintainer verification →Cloudflare hosting
Free tier eligible within limits
The documented Tempik deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs.
Hosting requirements
- Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits.
- Keep aggregate D1 use below 5 million rows read/day, 100,000 rows written/day and 5 GB total storage; a request can touch many rows.
- Inbound Email Routing can use Workers Free, but processing consumes Workers quotas and requires a domain; arbitrary-recipient outbound email requires Workers Paid.
- Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations.
Sources checked 01/10/2026
Repository snapshot: 36d05ed. Hosting eligibility reflects the deployment documentation and listed assumptions.
- temp-mail ↗
Tempik is a **self-hosted disposable email** service that runs entirely on **Cloudflare Workers** — no VPS required. It uses Cloudflare Email Workers to receive inbound email, D1 for storage, and serves a clean web UI from the edge.
- workers ↗
name = "tempik" main = "src/index.ts" compatibility_date = "2025-06-01" # Set workers_dev to false when using your own domain workers_dev = false # ---- D1 Database ---- # Step 1: run `npx wrangler d1 create tempik-db` # Step 2: copy the database_id here [[d1_databases]] binding = "DB" database_name = "tempik-db" database_id = "" # ---- Email Worker ---- [email] ac
- d1 ↗
dev = false # ---- D1 Database ---- # Step 1: run `npx wrangler d1 create tempik-db` # Step 2: copy the database_id here [[d1_databases]] binding = "DB" database_name = "tempik-db" database_id = "" # ---- Email Worker ---- [email] action = "process" # ---- Custom domain routes ---- # CHANGE THIS to your own domain (e.g. tempik.example.com) [[routes]] pattern = "tempik.YOURDOMAIN.com" custom_domain = true # ---- Environment variables ---- # CHANGE THESE to your own domain [vars] APP_NAME = "Tem
- email-workers ↗
Temp Mail on Cloudflare Workers Tempik is a **self-hosted disposable email** service that runs entirely on **Cloudflare Workers** — no VPS required. It uses Cloudflare Email Workers to receive inbound email, D1 for storage, and serves a clean web UI from the edge. > **Repo**: [github.com/hirotomasato/tempik](https://github.com/hirotomasato/tempik) --- ## How it works ``` Sender → Cloudflare MX → Email Worker (email handler) │ ▼ D1 Database (SQLite) │ ▼ Worker HTTP handler → Web UI + API ``` - **No VPS** — everything runs on Clo
- free-tier-eligible ↗
name = "tempik" main = "src/index.ts" compatibility_date = "2025-06-01" # Set workers_dev to false when using your own domain workers_dev = false # ---- D1 Database ---- # Step 1: run `npx wrangler d1 create tempik-db` # Step 2: copy the database_id here [[d1_databases]] binding = "DB" database_name = "tempik-db" database_id = "" # ---- Email Worker ---- [email] ac
- free-tier-eligible ↗
dev = false # ---- D1 Database ---- # Step 1: run `npx wrangler d1 create tempik-db` # Step 2: copy the database_id here [[d1_databases]] binding = "DB" database_name = "tempik-db" database_id = "" # ---- Email Worker ---- [email] action = "process" # ---- Custom domain routes ---- # CHANGE THIS to your own domain (e.g. tempik.example.com) [[routes]] pattern = "tempik.YOURDOMAIN.com" custom_domain = true # ---- Environment variables ---- # CHANGE THESE to your own domain [vars] APP_NAME = "Tem
- free-tier-eligible ↗
up>1, 2, 3, 4</sup> | Duration | CPU time | | --- | --- | --- | --- | | **Free** | 100,000 per day | No charge for duration | 10 milliseconds of CPU time per invocation | | **Standard** | 10 million included per month <br> +$0.30 per additional million | No charge or limit for duration | 30 million CPU milliseconds included per month<br> +$0.02 per additional million CPU milliseconds<br><br> Max of [5 minutes of CPU time](https://developers.cloudflare.com/workers/platform/limits/#account-plan-limits) per invocation (default: 30 seconds)<br> Max of 15 minutes of CPU time per [Cron Trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) or [Queue Consumer](https://developers.cloudflare.co
- free-tier-eligible ↗
oudflare.com/workers/platform/pricing/#workers) | | --- | --- | --- | | Rows read | 5 million / day | First 25 billion / month included + $0.001 / million rows | | Rows written | 100,000 / day | First 50 million / month included + $1.00 / million rows | | Storage (per GB stored) | 5 GB (total) | First 5 GB included + $0.75 / GB-mo | Track your D1 usage To accurately track your usage, use the [meta object](https://developers.cloudflare.com/d1/worker-api/return-object/), [GraphQL Analytics API](https://developers.cloudflare.com/d1/observability/metrics-analytics/#query-via-the-graphql-api), or the [Cloudflare dashboard ↗︎](https://dash.cloudflare.com/?to=/:account/workers/d1/). Select your D1 database, then vie
- free-tier-eligible ↗
g is based on your Cloudflare plan and email usage. ## Plan pricing Email Routing is available on both the Workers Free and Workers Paid plans. Sending to arbitrary recipients requires the Workers Paid plan. Sending to [verified destination addresses](https://developers.cloudflare.com/email-service/configuration/email-routing-addresses/#destination-addresses) in your account is free on all plans, including when only Email Routing is configured. | | Workers Free | Workers Paid | | --- | --- | --- | | **Outbound emails (Email Sending)** | Not available | 3,000 included per month, then $0.35 per 1,000 emails | | **Inbound emails (Email Routing)** | Unlimited | Unlimited | The 3,000 included emails apply per a
- MIT ↗
MIT License Copyright (c) 2026 masantoid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRING
- architecture ↗
name = "tempik" main = "src/index.ts" compatibility_date = "2025-06-01" # Set workers_dev to false when using your own domain workers_dev = false # ---- D1 Database ---- # Step 1: run `npx wrangler d1 create tempik-db` # Step 2: copy the database_id here [[d1_databases]] binding = "DB" database_name = "tempik-db" database_id = "" # ---- Email Worker ---- [email] ac
- architecture ↗
dev = false # ---- D1 Database ---- # Step 1: run `npx wrangler d1 create tempik-db` # Step 2: copy the database_id here [[d1_databases]] binding = "DB" database_name = "tempik-db" database_id = "" # ---- Email Worker ---- [email] action = "process" # ---- Custom domain routes ---- # CHANGE THIS to your own domain (e.g. tempik.example.com) [[routes]] pattern = "tempik.YOURDOMAIN.com" custom_domain = true # ---- Environment variables ---- # CHANGE THESE to your own domain [vars] APP_NAME = "Tem
What it can replace
Compare the workflow you need. These mappings describe overlap; full feature parity requires a separate comparison.
Disposable inbound addresses and viewing received mail; outbound sending, a permanent mailbox suite and managed privacy guarantees are excluded.
See supporting source ↗How it works
The shape of Tempik on Cloudflare, and how it stacks up against the rented tools it replaces.
Architecture
Diagram of deployment declarations at the reviewed commit. Each app has its own entrypoint; declared resources do not prove runtime calls. Follow file and line sources below.
View upstream source ↗Configuration and workflow sources
Reviewed commit 36d05edc7010. Files were read as data; upstream applications and CI jobs were not executed.
Deployment configuration · 1 files
Cloudflare Workers · compatibility 2025-06-01
tempik · default
Entrypoint: src/index.ts
Static assets: ./src/web
Configured route patterns: tempik.YOURDOMAIN.com
DB→ D1Static assets→ Static assets
Named environments are separate deployments. Bindings are shown only where declared. Configured routes are URL patterns, not verified application endpoints.
Runtime source · handlers, binding usage and workflow steps
Observed TypeScript/JavaScript declarations from Worker entrypoints and resolved relative imports. Calls and workflow steps may run conditionally; their listed order is not a proven end-to-end request flow. Router declarations may be mounted under a prefix or may not be registered. This shows code wiring, not a successful deployment or runtime test. Dynamic wiring, aliases and generated code may not resolve.
- L47 · api.get("/config")
- L58 · api.get("/session")
- L68 · api.get("/inboxes")
- L77 · api.post("/inboxes")
- L116 · api.delete("/inboxes/:address")
- L126 · api.get("/inboxes/:address/messages")
- L23 · getDomains calls (conditional paths may differ): filter, map, env.MAIL_DOMAIN.split, d.trim
- L27 · defaultDomain calls (conditional paths may differ): getDomains
- L31 · sessionId calls (conditional paths may differ): trim, c.req.header
- L35 · requireSession calls (conditional paths may differ): sessionId, c.status
Environment references: env.MAIL_DOMAIN · c.env.APP_NAME · c.env.WEB_HOST · c.env.DB
- L14 · handleEmail calls (conditional paths may differ): message.to.toLowerCase, message.from.toLowerCase, console.log, parser.parse, inboxExists, createInbox, Date.now, slice, crypto.randomUUID, insertMessage, console.error
Environment references: env.DB
- L24 · getInbox calls (conditional paths may differ): first, bind, db.prepare
- L28 · createInbox calls (conditional paths may differ): run, bind, db.prepare
- L32 · inboxExists calls (conditional paths may differ): first, bind, db.prepare
- L37 · getSessionInboxes calls (conditional paths may differ): then, all, bind, db.prepare
- L52 · getMessages calls (conditional paths may differ): then, all, bind, db.prepare
- L62 · insertMessage calls (conditional paths may differ): run, bind, db.prepare
- L77 · ensureSession calls (conditional paths may differ): run, bind, db.prepare
- L81 · sessionExists calls (conditional paths may differ): first, bind, db.prepare
- L88 · linkInboxToSession calls (conditional paths may differ): run, bind, db.prepare
- L101 · unlinkInboxFromSession calls (conditional paths may differ): run, bind, db.prepare
- L112 · isInboxInSession calls (conditional paths may differ): first, bind, db.prepare
Build and deployment pipeline · 0 GitHub Actions workflows
Repository CI declarations, separate from runtime request processing. Job dependencies and conditions are shown as written; long commands are shortened with an ellipsis; a workflow file does not prove a recent successful run.
No GitHub Actions workflow was found in the collected tree. Deployment may be manual or configured elsewhere.
deploy: wrangler deploy
Repository README
View original on GitHub ↗Full upstream document by @hirotomasato · README.md · snapshot 36d05ed
Tempik — Disposable Temp Mail on Cloudflare Workers
Tempik is a self-hosted disposable email service that runs entirely on Cloudflare Workers — no VPS required. It uses Cloudflare Email Workers to receive inbound email, D1 for storage, and serves a clean web UI from the edge.
How it works
Sender → Cloudflare MX → Email Worker (email handler)
│
▼
D1 Database (SQLite)
│
▼
Worker HTTP handler → Web UI + API
- No VPS — everything runs on Cloudflare's edge
- No Postfix — Cloudflare Email Workers handle SMTP ingestion natively
- No Docker — just
wrangler deploy - Zero cost — fits within Cloudflare's free tier
Prerequisites
Before you start, you need:
| Requirement | Details |
|---|---|
| Cloudflare account | Sign up here (free) |
| A domain | Must be added to Cloudflare (nameservers pointed to Cloudflare) |
| Node.js | v18 or later (download) |
| npm | Comes with Node.js |
Step 1 — Clone & install dependencies
git clone https://github.com/hirotomasato/tempik.git
cd tempik
npm install
Step 2 — Login to Cloudflare
npx wrangler login
This opens a browser window. Log in with your Cloudflare account and approve the OAuth scopes.
What scopes are needed? Wrangler will request permissions for Workers, D1, Email Routing, Pages, and more. You must approve all of them so the CLI can create the database and deploy the worker.
Verify you're logged in:
npx wrangler whoami
Step 3 — Configure wrangler.toml
Open wrangler.toml and replace the placeholder values with your own:
name = "tempik"
main = "src/index.ts"
compatibility_date = "2025-06-01"
# Set to false when using your own domain (skip workers.dev)
workers_dev = false
# D1 Database — leave database_id empty for now, we'll fill it in Step 4
[[d1_databases]]
binding = "DB"
database_name = "tempik-db"
database_id = ""
# Email Worker
[email]
action = "process"
# Custom domain — CHANGE THIS to your own domain
[[routes]]
pattern = "tempik.YOURDOMAIN.com"
custom_domain = true
# Environment — CHANGE THESE
[vars]
APP_NAME = "Tempik"
MAIL_DOMAIN = "YOURDOMAIN.com"
WEB_HOST = "tempik.YOURDOMAIN.com"
# Static assets (don't change)
[assets]
directory = "./src/web"
[observability]
enabled = true
All three vars + the routes pattern must be updated:
YOURDOMAIN.com→ your actual domain (e.g.example.com)tempik.YOURDOMAIN.com→ the subdomain for the web UI
Step 4 — Create the D1 database
npx wrangler d1 create tempik-db
You'll see output like:
✅ Successfully created DB 'tempik-db'
[[d1_databases]]
binding = "DB"
database_name = "tempik-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Copy the database_id into your wrangler.toml.
Step 5 — Apply the database schema
Push the schema to your remote D1 database on Cloudflare:
npx wrangler d1 execute tempik-db --remote --file=src/db/schema.sql
This creates four tables:
inboxes— email addressesmessages— received emailssessions— browser session tokenssession_inboxes— which inboxes belong to which session
Note: The
--remoteflag is important — without it, the schema only applies locally. You want it on Cloudflare's servers.
Step 6 — Deploy the Worker
npx wrangler deploy
This does three things:
- Uploads the TypeScript Worker code
- Uploads the static frontend files (HTML/CSS/JS) to Cloudflare Assets (edge CDN)
- Registers the custom domain route
After a successful deploy, you'll see:
Deployed tempik triggers
tempik.YOURDOMAIN.com (custom domain)
Step 7 — Setup DNS on Cloudflare
7a. Web UI (automatic)
Cloudflare automatically creates the DNS record for your Worker's custom domain. If it doesn't:
- Go to Cloudflare Dashboard → Workers & Pages → tempik → Settings → Domains
- The custom domain
tempik.YOURDOMAIN.comshould already be listed
7b. MX Records (automatic with Email Routing)
Email Routing should already be enabled on your domain. Verify:
npx wrangler email routing settings YOURDOMAIN.com
It should show Enabled: true. The catch-all rule is also automatically set up — every *@YOURDOMAIN.com is routed to the tempik Worker:
npx wrangler email routing rules list YOURDOMAIN.com
Expected output:
Catch-all rule: enabled, action: worker:tempik
7c. SPF Record (optional but recommended)
If you don't already have an SPF record, add one so emails don't get flagged as spam:
| Type | Name | Content |
|---|---|---|
| TXT | @ |
v=spf1 include:_spf.mx.cloudflare.net ~all |
Step 8 — Test it
- Open
https://tempik.YOURDOMAIN.comin your browser - Click New → Random to create a disposable address
- Send an email from Gmail/any provider to that address
- Click Refresh — the email appears in your inbox
Commands cheat sheet
| Command | What it does |
|---|---|
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 (for dev) |
npx wrangler dev |
Run Worker locally |
npx wrangler tail |
Stream live logs from production |
npx wrangler d1 execute tempik-db --remote --command="SELECT * FROM messages LIMIT 10" |
Query the database |
Check if emails are being received
npx wrangler d1 execute tempik-db --remote --command="SELECT * FROM messages ORDER BY received_at DESC LIMIT 5;"
Watch live logs
npx wrangler tail --format pretty
Then send a test email — you'll see the Worker processing it in real time.
Project structure
tempik/
├── wrangler.toml # Worker config, D1 binding, routes, env vars
├── package.json
├── tsconfig.json
├── .gitignore
└── src/
├── index.ts # Entry point: fetch() + email() handlers
├── email-handler.ts # Parses inbound email via PostalMime → D1
├── api/
│ └── routes.ts # Hono router: /api/config, /api/session, /api/inboxes, /api/messages
├── db/
│ ├── schema.sql # D1 tables (inboxes, messages, sessions, session_inboxes)
│ └── queries.ts # Typed query functions
├── utils/
│ └── random-address.ts # Human-like random email generator
└── web/
├── index.html # Frontend UI
├── app.js # Frontend logic (vanilla JS)
└── styles.css # Dark theme styles
Tech stack
| Layer | Tech |
|---|---|
| Runtime | Cloudflare Workers |
| Router | Hono |
| Email parsing | PostalMime |
| Database | Cloudflare D1 (SQLite) |
| Static hosting | Cloudflare Workers Assets (edge CDN) |
| Language | TypeScript |
| CLI | Wrangler v4 |
Troubleshooting
"This site can't be reached / DNS_PROBE_FINISHED_NXDOMAIN"
Your domain's nameservers are not pointed to Cloudflare, or the DNS record hasn't propagated yet. Check:
dig +short YOURDOMAIN.com NS
Should show *.ns.cloudflare.com. Propagation can take up to 24 hours after changing nameservers.
Emails not appearing in the web UI
- The email was received but the inbox hasn't been linked to your browser session. Click New → type the exact local-part → click Create to claim it.
- Check the database:
npx wrangler d1 execute tempik-db --remote --command="SELECT * FROM messages ORDER BY received_at DESC LIMIT 5;" - Check live logs:
npx wrangler tail --format pretty
"Unexpected fields found in top-level field: email"
This is a known wrangler warning — it's cosmetic. The [email] config works fine. Cloudflare is still stabilizing the Email Worker integration.
Wrangler version mismatch
This project uses Wrangler v4. If you're on v3:
npm install --save-dev wrangler@4
License
MIT
Developer by masantoid
Frequently asked about Tempik
What is Tempik?+
Tempik is a self-hosted Temp Mail alternative built on the Cloudflare developer platform. Create temporary addresses and view incoming mail from a Cloudflare Worker.
What does Tempik replace?+
Tempik is listed as an alternative to Temp Mail. Compare the features and tradeoffs before migrating.
What Cloudflare primitives does Tempik use?+
Tempik is built on D1, Email Workers, Workers.
How much does Tempik cost to run?+
The documented Tempik deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs. Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits. Keep aggregate D1 use below 5 million rows read/day, 100,000 rows written/day and 5 GB total storage; a request can touch many rows. Inbound Email Routing can use Workers Free, but processing consumes Workers quotas and requires a domain; arbitrary-recipient outbound email requires Workers Paid. Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations. Check current Cloudflare pricing before deploying.
Is Tempik open source?+
The upstream repository declares the MIT license. Read its terms at https://raw.githubusercontent.com/hirotomasato/tempik/36d05edc7010039664716559acd3d623d5738188/LICENSE. Source code and contributor credit are available at https://github.com/hirotomasato/tempik.

Discussion · 0
sign in to comment →