← All docs

Email system

How Sponic Gardens email works end-to-end — Cloudflare for inbound, Resend for outbound, Gmail in front of both.
2026-05-03 Architecture Touches: Cloudflare · Resend · Gmail · Bitwarden

Companion doc

For step-by-step "how do I send mail as [email protected] from my Gmail" instructions, see Send mail from @sponicgardens.com via Gmail. This page is the architecture / current-state map.

One-paragraph summary

Inbound: mail to any @sponicgardens.com address hits Cloudflare's MX, Email Routing matches it against rule literals (or the catch-all), and forwards to a verified Gmail destination. Outbound: Gmail's "Send mail as" relays through Resend's SMTP gateway (smtp.resend.com:587), which signs the message with our DKIM key on the sponicgardens.com zone and ships it via Amazon SES under the hood. Replies come back to the alias and re-enter the inbound flow. No real mailboxes; everything is aliases plus filters.

Domains

DomainStatusRole
sponicgardens.com primary Live marketing site (sponicgardens.com), intranet (in.sponicgardens.com), and all email. Resend-verified. CF Email Routing active.
sponicgarden.com deprecated Old single-s domain. Web traffic redirects to sponicgardens.com. Email Routing still active (catch-all → journeymistique) so old correspondents don't bounce. Resend domain still registered but should be removed once no further mail expected.
spogn.com active Short-domain. Web redirects to sponicgardens.com. Email forwards via chain (sonia/[email protected] → @sponicgardens.com → gmails) so future Workspace migration only touches the Sponicgardens side.

Inbound flow (Cloudflare Email Routing)

recipient hits Send (To: [email protected]) → DNS MX lookup → route1/2/3.mx.cloudflare.net (priority 41/70/10) → CF SMTP gateway accepts → Email Routing rule engine matches "to" literal → rewrites To: to the destination address → CF re-sends via SMTP to Gmail (gmail-smtp-in.l.google.com) → lands in destination inbox

Active rules on sponicgardens.com

Match (To)Forward toStatus
[email protected][email protected]enabled
[email protected][email protected]enabled
[email protected][email protected]enabled
[email protected][email protected]enabled
catch-all (everything else)(disabled, drops)disabled

Note: Catch-all is disabled on sponicgardens.com — mail to an undefined alias bounces. On sponicgarden.com the catch-all is enabled and forwards to journeymistique, since old correspondents may still type the deprecated domain.

Active rules on sponicgarden.com (deprecated)

Match (To)Forward toStatus
[email protected][email protected]enabled
catch-all[email protected]enabled

Verified destinations (account-wide on wingsiebird CF account)

Cloudflare requires every destination address to be verified before any rule can target it. Verification = CF sends a one-time link to the address; the human clicks it.

Outbound flow (Resend SMTP)

Gmail compose (From: [email protected] via "Send mail as") → SMTP submission to smtp.resend.com:587 (STARTTLS, user "resend", pass = Resend API key) → Resend signs with DKIM key at resend._domainkey.sponicgardens.com → Resend hands off to Amazon SES (region us-east-1) → SES delivers to recipient → bounces / FBLs flow back to send.sponicgardens.com (MX → feedback-smtp.us-east-1.amazonses.com)

DNS records that make it work (on sponicgardens.com zone, wingsiebird CF account)

TypeNameValuePurpose
MX 41@route1.mx.cloudflare.netInbound — CF Email Routing accepts mail
MX 70@route2.mx.cloudflare.net
MX 10@route3.mx.cloudflare.net
TXT@v=spf1 include:_spf.mx.cloudflare.net ~allSPF for inbound (CF auto-adds)
TXTresend._domainkeyp=MIGfMA0GCSqGSIb3... (Resend DKIM)Outbound DKIM signing
MX 10sendfeedback-smtp.us-east-1.amazonses.comOutbound bounces / FBL
TXTsendv=spf1 include:amazonses.com ~allSPF on the bounce subdomain

Resend account state

How to add things

A new alias forwarding to an existing verified gmail

Most common case — e.g. [email protected][email protected]. One CF API call:

export BW_PASSWORD=$(security find-generic-password -a "[email protected]" -s "bitwarden-cli" -w)
SESSION=$(/opt/homebrew/bin/bw unlock --passwordenv BW_PASSWORD --raw 2>/dev/null)
TOK=$(/opt/homebrew/bin/bw get item d0fdd0eb-e175-4bb4-ada4-b43a003fdd99 --session "$SESSION" | jq -r '.login.password')
ZONE="b0129785b612f8b7b34f7af37c449a37"

curl -sS -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE}/email/routing/rules" \
  -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
  -d '{
    "name": "[email protected][email protected]",
    "matchers": [{"type":"literal","field":"to","value":"[email protected]"}],
    "actions":  [{"type":"forward","value":["[email protected]"]}],
    "enabled": true,
    "priority": 10
  }' | jq .success

A new gmail destination (must verify before use)

ACCT="9cd3a280a54ce2a5b382602f0247b577"
curl -sS -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCT}/email/routing/addresses" \
  -H "Authorization: Bearer $TOK" -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}' | jq .

CF sends a verification email directly to that gmail (it does not go through any CF rule, so the address must really exist and you must have access). Click the link, then it can be used as a forward target.

Forwarding to multiple destinations

Multi-destination is silently broken — one rule per destination

The CF API accepts "value": ["a@x", "b@x"] on a forward action and the dashboard shows it as valid — but the MTA only delivers when the array has exactly one entry. Multi-value forwards return 550 5.1.1 Address does not exist at SMTP time, indistinguishable from a non-existent address. The API also rejects multiple action objects on one rule (error 2007: only one action per rule is allowed).

To fan out: create one rule per destination, all with the same to matcher. CF allows multiple rules with identical matchers; both/all will fire.

The catch-all rule uses a special endpoint

The catch-all has a regular rule id but the generic PUT /rules/{id} endpoint returns code 2020: Invalid rule operation. Always use:

PUT /zones/{zone}/email/routing/rules/catch_all

with the same body shape (matchers / actions / enabled).

Send mail as (Gmail outbound)

One Send mail as entry per alias, set up in Gmail Settings → Accounts. Use Resend SMTP creds (above). Verification email round-trips through CF (alias → destination gmail → you click). Full step-by-step: Send mail from @sponicgardens.com via Gmail.

Known gotchas

Diagnostic recipes

Probe a rule directly at CF's MTA (skip Resend)

( sleep 1; printf "EHLO test.com\r\n"; sleep 0.3; printf "MAIL FROM:<[email protected]>\r\n"; \
  sleep 0.3; printf "RCPT TO:<[email protected]>\r\n"; sleep 0.3; printf "QUIT\r\n"; sleep 0.3 ) \
  | openssl s_client -starttls smtp -crlf -quiet -connect route1.mx.cloudflare.net:25 2>&1 \
  | grep -E "Address does not exist|2.1.0 Ok"

2.1.0 Ok after RCPT TO → CF accepts. 550 Address does not exist from a rule the API shows as enabled → either the multi-destination bug or an unverified destination.

Send a real test via Resend

RESEND_KEY=$(/opt/homebrew/bin/bw get item 87184c25-8884-497c-94d2-b41600586a6e --session "$SESSION" \
  | jq -r '.fields[]|select(.name=="API Key (Sending Only)").value')
curl -sS -X POST https://api.resend.com/emails \
  -H "Authorization: Bearer $RESEND_KEY" -H "Content-Type: application/json" \
  -d '{"from":"[email protected]","to":["[email protected]"],"subject":"chain-test","text":"body"}'

Returns {"id":"…"} on queue success. Check that the message lands in the destination inbox within a minute. Always send from a domain alias, not from your real gmail (Gmail self-loop dedup will hide it).

Future work

Doc owner: Rahul. Last updated 2026-05-03. Operational secrets in BW folder devops-sponic; full token / endpoint / ID index lives in the auto-memory at ~/.claude/projects/-Users-rahulio-Documents-CodingProjects-sponic/memory/service-access.md.