Skip to content

Repository files navigation

email-notifier

Cloudflare Email Worker that, for each incoming email, forwards it to another mail server and posts a Discord notification chosen by the recipient's username.

Mail to {username}@your-domain (e.g. user1@gophercon.jp) is forwarded to {username}@FORWARD_EMAIL_DOMAIN and posted as a Discord embed to the webhook mapped to {username}. Usernames with no mapping are forwarded only (no error).

Domain-agnostic; runtime dependencies kept to postal-mime (MIME parsing) and html-to-text (HTML body → plain text).

How it works

email() (src/index.ts) starts message.forward() without awaiting (concurrent with the notification), looks up the webhook for the username — parsing DISCORD_WEBHOOK_MAP once per instance — posts the email as a Discord embed with the body trimmed to Discord's limits, then awaits the forward. Notification errors are logged and swallowed so forwarding is never affected.

Configuration

Two values, read as Workers secrets in production and dev vars locally:

Name Description
DISCORD_WEBHOOK_MAP JSON object mapping username → Discord webhook URL.
FORWARD_EMAIL_DOMAIN Domain incoming mail is forwarded to.

Both live in a git-ignored .env.yaml (see .env.yaml.example):

cp .env.yaml.example .env.yaml   # then edit
bun run gen:dev-vars             # -> .dev.vars for local dev

.env.yaml is for local dev only; in production the same two values are Workers secrets set in the Cloudflare dashboard (see Deployment).

Development

Toolchain (bun, node) is pinned in mise.toml; installs enforce a 3-day release cooldown (bunfig.toml) for supply-chain safety.

mise install        # pinned bun/node (optional)
bun install
bun run gen         # gen:cf-types + gen:dev-vars
bun run dev         # vite dev, loads .dev.vars
bun run typecheck   # tsc --noEmit
bun run test        # vitest (Workers runtime)
bun run build       # vite build

Cloudflare deploys on merge to main (see Deployment); there is no local deploy script.

Deployment

Pull-based, via Cloudflare Workers Builds: Cloudflare builds this repository itself, on push to main and on pull requests. Nothing deploys from GitHub Actions and the repository holds no Cloudflare credentials.

Secrets and Email Routing are set on the Worker in the Cloudflare dashboard, so changing a webhook or the forward domain needs no commit.

About

Cloudflare Worker to forward incoming emails to Discord webhooks and a specified mail server

Resources

Stars

0 stars

Watchers

1 watching

Forks

Contributors

Languages