A bridge to send inbound email from CloudMailin to a Discord channel webhook, deployed as a Cloudflare Worker.
Created with assistance from OpenAI's ChatGPT and Codex.
Requires the following two environment variables
CLOUDMAILIN_BASIC_AUTH— theuser:passwordpair used for basic auth in the CloudMailin webhook URL.DISCORD_WEBHOOK_URL— provided by Discord. Can be found by going to "Edit Channel" > "Integrations" > "Webhooks" > specific webhook > "Copy Webhook URL".
For local development, copy .dev.vars.example to .dev.vars and fill in your values so wrangler dev can read them. For deployed environments, add the secrets to your Worker with:
npx wrangler secret put CLOUDMAILIN_BASIC_AUTH
npx wrangler secret put DISCORD_WEBHOOK_URLWrangler will prompt you for each value and store them securely on Cloudflare.
Run
npm run deployThe exposed webhook endpoint for the bridge is https://<your-worker-domain>/webhooks/cloudmailin.
Set the CloudMailin target URL to include basic auth:
https://user:password@<your-worker-domain>/webhooks/cloudmailin
This worker expects the CloudMailin JSON POST format. It sends the plain field to Discord, splitting into multiple 2,000-character messages when needed.
The Discord message includes key email headers plus as much of the plain body as fits. Example:
From: `Message Sender <sender@example.com>`
Subject: **Test Subject**
Date: `Mon, 16 Jan 2012 17:00:01 +0000`
Attachments: `2` (file.txt, file.txt)
This is a test email message.
If the plain body exceeds Discord's 2,000 character limit, the worker sends multiple sequential Discord messages. Chunking happens on word boundaries when possible.
When multiple messages are required, each message includes a part indicator after the header (and at the top of continuation messages), like [part 1/3].
Discord webhook requests are sent with ?wait=true so the Worker waits for message creation before posting the next chunk.
If Discord responds with 429 or a 5xx, the Worker retries with exponential backoff and honors Retry-After when provided.
/health— health check for the service/webhooks/cloudmailin— endpoint that accepts inbound email payloads from CloudMailin