BACKUP_TABLES is a hardcoded list, and the migrations that added email_templates, calendar_events (0020) and auto_reply_deliveries (0022) never updated it. Those three tables are absent from every backup, and because restoreDatabaseRecords only touches the listed tables, restoring into an empty database silently loses calendar events and email templates with nothing reporting a problem. Add the three tables, and add assertBackupTablesCoverDatabase, which compares sqlite_master against BACKUP_TABLES and aborts the backup naming any unlisted table. A backup that fails loudly is recoverable; one that silently omits a table is only discovered during a restore, when the data is already gone. The three tables are appended, so the reverse-order delete still removes children before parents and the forward-order insert still writes them after users and mailboxes, which they reference. Extending the list would by itself have broken restores of existing backups: isDatabaseBackupDocument required every BACKUP_TABLES entry to be present, and documents written before this change have only the original nineteen. Split out REQUIRED_BACKUP_TABLES so tables added later are optional on read, and fill absent ones with an empty array before validation. Documents missing an original table are still rejected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mailflare
Mailflare is a self-hosted email inbox for custom domains, built on Cloudflare.
What you can do
- Connect domains and set up Cloudflare Email Routing from the dashboard.
- Create personal and shared mailboxes with delegated access.
- Send and receive email with attachments, rich formatting, signatures, and automatic replies.
- Organize mail with search, custom folders, stars, snoozing, archive, spam, and trash.
- Create routing rules to store, forward, reject, or categorize incoming messages.
- Get real-time inbox updates and new-message notifications.
- Import and export mail, manage contacts, and block unwanted senders.
- Manage accounts, permissions, API keys, webhooks, audit logs, and database backups.
How it works
Mailflare runs in your Cloudflare account. Email Routing delivers incoming messages to the app, while Cloudflare's email service handles outgoing messages. Your mail data stays in your own D1 database and attachments are stored in your own R2 bucket.
How much does it cost?
You can setup Mailflare and receive email for free
A Paid Worker plan ($5/month) is required to send email (and it's recommend to have a smooth experience)
Deploy
The easiest way to get started is with the Deploy to Cloudflare button above. You will need:
- A Cloudflare account.
- A domain managed by Cloudflare.
- A Cloudflare API token that Mailflare can use to configure email routing.
After deployment, open your Mailflare URL and follow the first-run setup. The setup checks your Cloudflare configuration, creates the initial account, and helps you connect your first domain.
See the deployment guide for required permissions, manual deployment, backups, updates, and custom Worker names.
Local development
cp .dev.vars.example .dev.vars
npm install
npm run db:migrate:local
npm run dev
Add your Cloudflare credentials to .dev.vars, then open http://localhost:3000. For sample local data, run npm run db:seed while the development server is running.
Documentation
License
See LICENSE.
