Mailbridge is a security-focused Node.js mail gateway that connects Cloudflare Email Routing to a private SMTP server. It can also relay trusted outbound SMTP traffic through SendGrid, Resend, Mailgun, or Cloudflare Email Service.
For complete installation, architecture, configuration, security, operations, and troubleshooting documentation, use the Mailbridge Wiki.
Inbound:
Cloudflare Email Routing
-> Worker encryption
-> ciphertext-only R2 storage
-> Cloudflare Queue object reference
-> authenticated Mailbridge webhook
-> local decryption and spam screening
-> private SMTP server
Outbound:
trusted CIDR-restricted SMTP client
-> Mailbridge relay
-> SendGrid / Resend / Mailgun / Cloudflare Email Service
- Public-key envelope encryption before inbound mail reaches R2
- Authenticated Worker-to-Mailbridge webhook delivery
- SpamAssassin with local
spamdor Postmark SpamCheck mode - Optional Spamhaus and AI secondary screening
- Exchange-friendly spam headers and optional subject tagging
- Verified TLS support for private SMTP delivery
- Optional STARTTLS and CIDR-restricted outbound SMTP relay
- Configurable SMTP DATA size limit
- Four outbound provider integrations
- Encrypted local retry queue with separate secret storage
- Audit-only SQLite event database
- Optional in-container Cloudflare Tunnel
- Interactive configuration generator
- Explicit, exact-version plugin system for scanners and outbound providers
Requirements:
- Node.js 22 or newer
- Docker with Docker Compose
- Cloudflare Email Routing, Workers, R2, and Queues
- A private SMTP server
Clone the repository, install dependencies, and start the interactive setup:
npm install
npm run setupThe assistant creates .env, wrangler.toml, runtime directories, independent webhook secrets, the local queue master key, and the RSA keypair used for encrypted R2 handoff. It asks before overwriting existing configuration.
Optional scanners and outbound providers are installed as exact-version plugins. For example, use mailbridge-plugin-spamhaus@1.0.0; unversioned packages, latest, and version ranges are rejected. Plugins run in supervised child processes and receive only their declared namespaced settings and secrets.
Mailbridge discovers plugins from MAILBRIDGE_PLUGIN_DIR using mailbridge-plugin.json. A plugin declares one of three types:
provider: receivesdeliverwith the SMTP envelope and base64 RFC822 message.scanner: receivesscan; capabilities such asreputationandclassificationdetermine when it runs.middleware: receivestransformand may return a modified RFC822 message/envelope or reject delivery. This supports header editing, attachment removal, text inspection, redaction, and similar processing.
Middleware runs deterministically by manifest priority, then plugin ID. Plugins communicate over JSON Lines API version 1 and may also handle init, health, and shutdown. Configuration is namespaced in MAILBRIDGE_PLUGIN_CONFIG_FILE; secrets use MAILBRIDGE_PLUGIN_<PLUGIN_ID>_<SECRET_NAME>. Protected Mailbridge encryption and webhook secrets cannot be requested by a plugin. The setup assistant accepts exact-version community packages and prompts from manifest configuration/secret schemas.
See Plugin Development for the complete manifest, protocol, and middleware contracts.
Then run the Cloudflare commands printed by the assistant and start Mailbridge:
docker compose up -d --build
docker compose ps
docker logs -f mail-bridgeCheck the health endpoint:
curl http://127.0.0.1:3090/healthExpected response: OK.
See the wiki Quick Start for resource creation, Worker secrets, deployment, and validation.
The amd64 package supports Debian 11-13, Ubuntu 24.04/26.04, and Debian-based Proxmox Mail Gateway installations. On a Proxmox VE virtualization host, install Mailbridge in a dedicated Debian LXC or VM instead of directly on the hypervisor.
Install the repository signing key and select the current distribution codename:
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://deb.alghul.com/gpg.key \
| sudo gpg --dearmor --yes -o /etc/apt/keyrings/mailbridge-archive-keyring.gpg
. /etc/os-release
case "$VERSION_CODENAME" in
bullseye|bookworm|trixie|noble|resolute) ;;
*) echo "Unsupported distribution: $VERSION_CODENAME" >&2; exit 1 ;;
esac
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/mailbridge-archive-keyring.gpg] https://deb.alghul.com $VERSION_CODENAME main" \
| sudo tee /etc/apt/sources.list.d/mailbridge.list
sudo apt-get update
sudo apt-get install mailbridgeRun the interactive configuration assistant, review the generated settings, and start the service:
sudo mailbridge-setup
sudoedit /etc/mailbridge/mailbridge.env
sudo systemctl enable --now mailbridge
sudo systemctl status mailbridgeThe assistant creates the long runtime configuration, local encryption keys, queue secret, and Cloudflare Worker configuration. Follow its printed Wrangler commands to upload Worker secrets and deploy the Worker; never upload the generated private key.
- Inbound R2 objects contain ciphertext, never plaintext mail.
- The R2 decryption private key remains on the Mailbridge host.
- Local retry files are encrypted at rest.
- The SMTP relay is disabled and loopback-restricted by default.
- Relay STARTTLS and private SMTP certificate verification are preferred.
- Spam filtering fails closed unless explicitly configured otherwise.
- Spamhaus and AI screening are disabled by default.
- Generated secret-bearing configuration files use mode
0600.
Never commit .env, live wrangler.toml, private keys, provider credentials, tunnel tokens, data/, or secrets/.
Read the complete Security Model and repository Security Policy.
- Wiki Home
- Quick Start
- Architecture
- Inbound Delivery
- Outbound Relay and Providers
- Spam and Reputation Filtering
- Encrypted Queue and Audit
- Configuration Reference
- Cloudflare Setup
- Deployment
- Testing and Operations
- Troubleshooting
server.js Main Node.js backend
worker.js Cloudflare Worker entrypoint
lib/ Crypto, queue, filtering, transport, and provider modules
test/ Node test suite
scripts/setup.js Interactive configuration generator
Dockerfile Production image
docker-compose.yml Local/runtime deployment
entrypoint.sh Container startup and process supervision
This repository contains backend and Cloudflare edge code only; there is no browser frontend.
npm install
npm test
npm audit --omit=dev
npx wrangler deploy --dry-run --config wrangler.example.tomlFor container changes:
docker compose up -d --build
docker logs -f mail-bridgePreserve webhook authentication, ciphertext-only R2 storage, local private-key ownership, queue encryption, CIDR relay protections, and fail-closed filtering behavior. Add tests for changes to parsing, crypto, queues, spam logic, webhook handling, or providers.
See AGENTS.md and CLAUDE.md for repository-specific development guidance.
See LICENSE.