RepoDaily · 2026-09-01 · Infrastructure / Runtime

Mailflare review: self-hosted custom-domain email on Cloudflare Workers, D1, and R2

#16 Infrastructure / Runtime TypeScript +450 hieunc229/mailflare Open repository

Mailflare runs a full email inbox for custom domains inside your own Cloudflare account: Email Routing in, D1 and R2 storage, $5/month to send. A source-available license blocks commercial reuse.

Repo typeInfrastructure / Runtime
Best forProfessionals and small teams, already on Cloudflare, who want custom-domain email with messages in their own D1 database and attachments in their own R2 bucket
Risk levelMedium - restrictive source-available license, version 0.2.0 maturity, total Cloudflare lock-in
Time to evaluate1-2 hours via the Deploy to Cloudflare button plus first-run setup

Primary question: Can your mail stack live entirely on Cloudflare, and does the non-commercial source-available license match how you intend to use it?

89/100

RepoDaily adoption score

RepoDaily rates this as 89/100 (strong) for adoption: evidence, installation path, production risk, differentiation, license clarity, and AI/agent fit are scored from the article sources and adoption notes.

Directional score from RepoDaily sources and adoption notes, not a benchmark.Risk: Medium
100Evidence quality

4 source(s) across 4 source category/categories, plus a RepoDaily-specific evidence module when available.

100Installability

7 workflow step(s), 5 next-action step(s), and 3 command/install signal(s) were detected.

63Maintenance confidence

Trending momentum is +450 stars, with maintenance/release/issue signals counted when present.

96Production readiness

Risk is marked medium, with 6 security note(s) and 4 explicit skip condition(s).

100Differentiation

3 opportunity lens item(s), 5 alternative(s), and 5 type-specific section(s) support differentiation.

82License clarity

License source or license wording is present.

60Agent / AI fit

2 AI/agent-related signal(s) were detected in the article text and metadata.

Project overview

Mailflare, listed at version 0.2.0 in package.json, is a self-hosted email inbox for custom domains that runs entirely on Cloudflare. The README pitches it as 'professional email for professionals and teams,' and the feature list backs that up: personal and shared mailboxes with delegated access, sending and receiving with attachments, rich formatting, signatures and automatic replies, search, custom folders, stars, snoozing, archive, spam and trash, routing rules that store, forward, reject or categorize incoming messages, real-time inbox updates with new-message notifications, mail import/export, contact management, sender blocking, and an admin layer covering accounts, permissions, API keys, webhooks, audit logs and database backups.

Architecturally it is a Next.js application compiled for Cloudflare: package.json's deploy script runs `opennextjs-cloudflare build` followed by `OPEN_NEXT_DEPLOY=true wrangler deploy`. The data layer is drizzle-orm 0.45.2 against Cloudflare D1, with migrations applied through `wrangler d1 migrations apply DB`. The UI stack includes Radix UI primitives, TanStack Query 5.x, dayjs and lucide-react; mimetext 3.0.28 appears for MIME message construction and bcryptjs 3.0.3 sits in the dependency list. Incoming mail arrives through Cloudflare Email Routing, outgoing mail goes through Cloudflare's email service, messages persist in your own D1 database, and attachments live in your own R2 bucket.

The cost structure is unusually simple. Receiving email is free once the app is deployed. Sending requires a Paid Worker plan at $5/month, which the README also recommends having 'for a smooth experience.' There is no per-seat pricing anywhere in the source material - the only recurring line item is that Worker plan.

The main caveat is the license. Mailflare ships under the Mailflare Source-Available License (copyright 2026, Hieu Nguyen). It grants access, reading, running and modification for 'personal or internal business use' and explicitly prohibits selling, sublicensing, offering it or derivatives as a hosted service, SaaS product, template or starter kit, redistributing or mirroring copies, forking for resale or competing commercial use, and removing notices. In practice: run it for yourself or your company, but do not build a product on top of it.

Problem it solves

  • Custom-domain email normally means per-seat SaaS (Google Workspace, Microsoft 365, Zoho Mail), where message data and admin controls sit with the vendor
  • Classic self-hosting with Postfix/Dovecot or suites like Mailcow means operating a server, maintaining certificates, and defending IP reputation for deliverability
  • Shared addresses such as support@ or billing@ require alias plumbing or additional per-seat licenses
  • Permissions, audit logs, backups and API access are typically gated behind business-tier plans
  • Mailflare compresses the prerequisite list to three items from its README: a Cloudflare account, a domain managed by Cloudflare, and a Cloudflare API token

How it works

  1. Create a Cloudflare API token with Zone Read, Email Routing Edit, Email Sending Edit and Email Routing Rules Write permissions, scoped to the zones you will connect (per the CF_TOKEN binding description in package.json).
  2. Click Deploy to Cloudflare from the README; the Worker is deployed into your Cloudflare account.
  3. Open your Mailflare URL and complete first-run setup, which checks your Cloudflare configuration, creates the initial account, and walks you through connecting your first domain.
  4. Incoming mail is delivered by Cloudflare Email Routing to the app; CF_EMAIL_WORKER_NAME must match the deployed Worker name.
  5. Outgoing mail goes through Cloudflare's email service and requires the $5/month Paid Worker plan.
  6. Messages persist in your own D1 database; attachments are stored in your own R2 bucket.
  7. The admin layer manages accounts, permissions, API keys, webhooks, audit logs and database backups; automatic D1 backups use CF_AID, D1_DATABASE_ID and an optional D1_BACKUP_TOKEN secret.

Architecture read: Next.js on Workers, D1, R2

The deploy pipeline is concrete: `npm run deploy` executes `opennextjs-cloudflare build` and then `deploy:worker`, which runs `OPEN_NEXT_DEPLOY=true wrangler deploy`. The Next.js app is therefore compiled through OpenNext for Cloudflare (@opennextjs/cloudflare ^1.19.9) and shipped with Wrangler. Data lives on drizzle-orm ^0.45.2 against D1, with schema changes generated by `drizzle-kit generate` and applied via `wrangler d1 migrations apply DB` in local and remote variants.

The frontend leans on Radix UI primitives (dialog, dropdown-menu, select, tabs, toast), TanStack Query ^5.100.11, class-variance-authority, clsx, dayjs ^1.11.20 and lucide-react. mimetext ^3.0.28 handles MIME message construction and bcryptjs ^3.0.3 is in the dependency list. Notably, the CF_TOKEN binding description confirms the app itself calls Cloudflare's Zones and Email Routing APIs during onboarding - that is how the dashboard can configure email routing for your domains instead of making you do it in the Cloudflare console.

Deployment notes: prerequisites, cost and tokens

  • README prerequisites: a Cloudflare account, a domain managed by Cloudflare, and a Cloudflare API token the app can use to configure email routing
  • Receiving email is free; sending requires the $5/month Paid Worker plan, which the README also recommends for a smooth experience
  • CF_TOKEN should be created separately from Cloudflare's deploy/build token, with exactly Zone Read, Email Routing Edit, Email Sending Edit and Email Routing Rules Write on the zones you connect
  • TURNSTILE_SECRET_KEY paired with NEXT_PUBLIC_TURNSTILE_SITE_KEY gates login and first-run registration challenges
  • CF_EMAIL_WORKER_NAME must equal the deployed Worker name; rename the Worker and you must update this binding
  • docs/deployment.md covers required permissions, manual deployment, backups, updates and custom Worker names; docs/api.md and docs/troubleshooting.md round out the docs set

Try-it path: local development in four commands

  • `cp .dev.vars.example .dev.vars`, then add your Cloudflare credentials to `.dev.vars`
  • `npm install` followed by `npm run db:migrate:local` (which runs `wrangler d1 migrations apply DB --local`)
  • `npm run dev`, then open http://localhost:3000
  • Optional sample data: `npm run db:seed` while the dev server is running - the script is literally `curl -X POST http://localhost:3000/api/seed`
  • `npm run preview` builds and previews through opennextjs-cloudflare for a Cloudflare-like local run before any deploy

Maintenance risk: version 0.2.0 and a restrictive license

package.json declares version 0.2.0 and `private: true` - early numbering for software that already ships audit logs, API keys, webhooks and automated backups. Updates are dispatched by an admin update endpoint that triggers update.yml in GitHub Actions using GITHUB_UPDATE_TOKEN, a fine-grained GitHub token requiring Actions: write plus Contents: write/read on your installation repository (GITHUB_UPDATE_REPO points at the repo connected to the Worker, and GITHUB_UPDATE_REF optionally selects a branch). Self-update therefore runs through your copy of the repository and through a fairly powerful stored token.

The license constrains everything else. The Mailflare Source-Available License permits personal and internal business use only: no selling or sublicensing, no hosted/SaaS/template/starter-kit offerings, no redistribution or mirroring, no forking for resale or competing commercial use, and notices must remain intact. The repository listing shows no topics and no homepage, and package.json points to 'SEE LICENSE IN LICENSE'. Budget for internal deployment only.

Integration surface: what connects to Mailflare

  • API keys and webhooks are first-class admin features, documented in docs/api.md
  • Mail import/export and contact management are built into the app per the README
  • Audit logs record activity; D1 backups run against CF_AID and D1_DATABASE_ID, with D1_BACKUP_TOKEN stored as a secret (if omitted, backups reuse CF_TOKEN)
  • Legacy deployments can still authenticate with CF_EMAIL plus CF_API_KEY (Global API Key), though package.json recommends CF_TOKEN for new deployments

Who should pay attention?

Good fit if

  • Freelancers and professionals who want email on a domain they own without operating a mail server
  • Small teams that need shared mailboxes (support@, billing@) with delegated access instead of more per-seat licenses
  • Cloudflare customers who specifically want mail data in their own D1 database and R2 bucket
  • Internal-business-use deployments, which the license explicitly permits, including modification

Skip for now if

  • Anyone planning to resell, rebrand, mirror, or host Mailflare or a derivative as a service - the license forbids all of these
  • Teams that cannot accept Cloudflare lock-in; Email Routing, Workers, D1 and R2 are the entire architecture, with no alternative runtime shown in the source pack
  • Senders who need dedicated IPs or advanced deliverability tooling; outbound mail goes through Cloudflare's email service on a $5/month Worker plan
  • Organizations with open-source-only procurement rules - 'SEE LICENSE IN LICENSE' means source-available, not an OSI license

Risks and cautions

Medium

A broad admin feature set for a 0.2.0 app, but the license forbids commercial redistribution and hosted use, every data path depends on one Cloudflare account, and self-updates run through a GitHub token with write permissions.

  • The Mailflare Source-Available License prohibits selling, sublicensing, SaaS hosting, redistribution, and forking for competing commercial use
  • Version 0.2.0 with `private: true` signals early maturity despite the wide feature surface
  • The stack is Cloudflare-only: Email Routing, Workers, D1 and R2, with no portable deployment path in the source pack
  • Sending email requires the $5/month Paid Worker plan; only receiving is free
  • Self-update depends on GITHUB_UPDATE_TOKEN with Actions: write and Contents: write/read on your installation repository
  • Runs entirely in your Cloudflare account: mail data in your own D1 database, attachments in your own R2 bucket - nothing is hosted by the author
  • CF_TOKEN guidance calls for a dedicated token scoped to Zone Read, Email Routing Edit, Email Sending Edit and Email Routing Rules Write, separate from Cloudflare's deploy/build token
  • Login and first-run registration are gated by Cloudflare Turnstile (TURNSTILE_SECRET_KEY paired with NEXT_PUBLIC_TURNSTILE_SITE_KEY)
  • bcryptjs ^3.0.3 is present in the dependency list for credential handling
  • Audit logs and automatic D1 backups (CF_AID, D1_DATABASE_ID, optional D1_BACKUP_TOKEN secret) ship in the product per the README
  • D1_BACKUP_TOKEN should be stored as a secret; if omitted, backups reuse CF_TOKEN

Alternatives to compare

ApproachWhen to useTrade-off
Mailcow
You want a full self-hosted mail suite (Postfix/Dovecot-based) on your own VPS with Docker, independent of any cloud vendorFree and open source; you pay for the server
Stalwart
You want an all-in-one Rust mail server (JMAP/IMAP/SMTP) you run yourself with full protocol controlFree and open source; server costs apply
Mailu
You want a Docker-based self-hosted mail server with a web interface, outside CloudflareFree and open source; server costs apply
Cloudflare Email Routing alone
You only need forwarding for custom-domain addresses and read mail in an existing personal inboxFree for forwarding; sending requires your own arrangement
Zoho Mail / Google Workspace
You want a fully managed commercial suite with per-seat pricing and zero infrastructure to runPer-user monthly subscription

What this trend reveals

Serverless self-hosted email without a mail server

Mailflare swaps the VPS-plus-Postfix model for Cloudflare primitives: Email Routing for inbound, Workers for the app, D1 for messages, R2 for attachments. The open question is deliverability and quota behavior at real volume, which the source pack does not address.

Deploy on a throwaway domain, exchange mail with Gmail and Outlook recipients, and watch the audit log and D1 storage growth for a week.

Admin surface usually reserved for business tiers

Shared mailboxes with delegated access, API keys, webhooks, audit logs and automatic D1 backups are all in the README feature list - capabilities SaaS vendors typically bundle into business plans.

After first-run setup, create a second account, delegate a shared mailbox, issue an API key, and export one D1 backup.

Internal deployment as the sanctioned use case

The license explicitly permits internal business use and modification while forbidding commercialization, which positions Mailflare for companies that want their own inbox and will never redistribute it.

Have counsel read the Mailflare Source-Available License against your intended usage before a production domain goes live.

Best next action

Deploy Mailflare on a test domain before touching your primary domain

The first-run setup creates Email Routing configuration on whichever domain you connect, so start with a sandbox domain and a freshly scoped token.

  1. Create a Cloudflare API token with Zone Read, Email Routing Edit, Email Sending Edit and Email Routing Rules Write, limited to the test zone
  2. Click Deploy to Cloudflare from the README and complete first-run setup (configuration check, initial account, first domain)
  3. Set the Turnstile keys and confirm CF_EMAIL_WORKER_NAME matches the deployed Worker name
  4. Receive one message (free), then enable the $5/month Paid Worker plan and send one
  5. Read docs/deployment.md on backups and updates before connecting a domain you care about

RepoDaily verdict

Mailflare is a credible serverless take on self-hosted email: a real inbox with shared mailboxes, routing rules and admin tooling, all inside your own Cloudflare account with mail in your D1 and attachments in your R2. The 0.2.0 version, the Cloudflare-only architecture, and a source-available license that bans commercial reuse keep it squarely in personal-and-internal-deployment territory - which, at $5/month to send, is a trade many small teams will accept.

Sources