Email Setup — [email protected]
Operational runbook for wiring
[email protected](and friends) on the existing Cloudflare-hosted domain. CEO-executable, ~10 minutes, free for the F&F phase.
Phase 53.9 · Last updated: 2026-05-08 · Provider: Cloudflare Email Routing (recommended for F&F)
Why this guide exists
Arc OS sends outbound mail today (verification, password reset) via Resend with From: [email protected] — see shared/email.ts. But the domain has no inbound mail at all: dig MX arc-os.co returns empty, so anything sent to [email protected] bounces. That breaks:
- The footer
Supportlink (mailto:[email protected]) - The signup flow's "reply with questions" expectation
- Bug-report email fallback for users who don't open the in-app FeedbackWidget
- Any future "respond to user" workflow
This guide turns inbound on without buying a mailbox.
Pre-flight
- Cloudflare account with
arc-os.cozone (already true — NS recordsamir.ns.cloudflare.com/becky.ns.cloudflare.com) - Personal Gmail (or any working mailbox) ready to receive forwards
- 10 minutes
- DO NOT enable on Resend's domain verification step before this guide finishes — Cloudflare Email Routing publishes its own MX/SPF and you'll fight yourself
Phase A — Cloudflare Email Routing (FREE, recommended)
Step 1 — Enable Email Routing in Cloudflare dashboard
- Open https://dash.cloudflare.com → pick the arc-os.co zone
- Left sidebar → Email → Email Routing
- Click Enable Email Routing
- Cloudflare offers to add the required DNS records automatically — accept. It writes:
MX 10 amir.mx.cloudflare.net.MX 20 isaac.mx.cloudflare.net.MX 30 linda.mx.cloudflare.net.TXT v=spf1 include:_spf.mx.cloudflare.net ~all
- Verify the green check appears next to "DNS records configured correctly"
Step 2 — Verify your destination (Gmail) once
Cloudflare sends a one-time verification email to whatever address you'll forward to. Click the link.
Step 3 — Add forwarding rules
In Email Routing → Routes, click Create address. Add three:
| Custom address | Action | Destination |
|---|---|---|
[email protected] |
Forward to | <your-gmail>@gmail.com |
[email protected] |
Forward to | <your-gmail>@gmail.com |
[email protected] |
Forward to | <your-gmail>@gmail.com |
Optional: add a Catch-all route → forward to Gmail. Catches typos like
[email protected].
Step 4 — Send a test
echo "test from $(hostname) at $(date)" | mail -s "Email Routing test" [email protected]
Or just send from your phone. Should land in Gmail within ~10 seconds, with From: <whoever-sent-it> preserved and To: [email protected].
Step 5 — Reply from Gmail as [email protected] (optional but nice)
Cloudflare Email Routing is inbound-only — you can't SEND from [email protected]. Workaround using Gmail:
- Gmail → Settings → Accounts → Send mail as → Add another email address
- Address:
[email protected], Name:Arc OS Team - Outgoing SMTP: Gmail's own SMTP (Cloudflare doesn't proxy outbound)
- Verify via the code Gmail sends — the verification email lands back in Gmail via the forward rule, so it's instant
Gmail will let you compose with From: [email protected]. Recipients see it. Reply-To routes back to [email protected] → forward chain → Gmail.
Step 6 — Update CRM signup From: header
Already correct — shared/email.ts:32 defaults to Citadel <[email protected]>. Confirm RESEND_API_KEY is in the vault and Resend's arc-os.co domain is verified in their dashboard. Resend uses a separate set of DKIM CNAMEs (*.resend._domainkey) that don't conflict with Email Routing's MX/SPF.
If you also want signup confirmations to land at info@-routable addresses, no change needed — Resend just sends; Cloudflare just receives.
Phase B — DMARC (recommended after Phase A is verified)
DMARC protects the domain from spoofing. With both Cloudflare Email Routing (inbound) and Resend (outbound) live, add a TXT record to monitor:
Name: _dmarc.arc-os.co
Type: TXT
Value: v=DMARC1; p=none; rua=mailto:[email protected]; pct=100
p=none collects reports without rejecting anything. After 2 weeks of clean reports, escalate to p=quarantine then p=reject.
Phase C — Outgrow forwards → real mailbox (later)
When forwards are no longer enough (separate inboxes per role, calendar invites, mobile apps, send-from-domain reliably):
| Provider | Cost | Setup time | Pros |
|---|---|---|---|
| Zoho Mail Lite | $1/user/mo (or free for ≤5 users with Zoho branding) | 30 min | Full inbox, mobile app, send from info@ natively |
| Google Workspace | $6/user/mo | 30 min | Best-in-class Gmail + Calendar + Drive + admin console |
| Fastmail | $5/user/mo | 30 min | Privacy-focused, no ads, fast UI |
Migration path from Cloudflare → mailbox: delete the forwarding rule for the address you're moving (e.g. info@), update MX records to the new provider, leave Cloudflare Email Routing on for the addresses you still want to forward (e.g. bugs@ could stay forwarded forever).
Don't migrate prematurely. F&F mail volume rarely justifies the cognitive overhead of a separate inbox.
Verification checklist
After completing Phase A:
-
dig MX arc-os.coreturns 3 Cloudflare records -
dig TXT arc-os.coincludesv=spf1 include:_spf.mx.cloudflare.net - Test email to
[email protected]lands in Gmail in <30s - CRM AppFooter
Supportlink works (now points toinfo@) - FeedbackWidget success state mentions
[email protected] - README contact line works
- Resend domain
arc-os.costill shows green in dashboard (no DNS conflict)
After completing Phase B:
-
dig TXT _dmarc.arc-os.coreturns the policy - First DMARC report received at
[email protected]within 24h
Action items for CEO (cannot be automated)
- Right now: open Cloudflare → Email → enable Email Routing → accept DNS → verify Gmail destination → add 3 forwarding rules. ~7 minutes.
- Optional: Gmail "Send mail as" setup. ~3 minutes.
- Optional: drop the DMARC TXT record. ~1 minute.
After step 1 completes, ping back and we close issue #39.
Reference
- Cloudflare Email Routing docs: https://developers.cloudflare.com/email-routing/
- Resend domain verification: https://resend.com/docs/dashboard/domains/introduction
- Existing CRM email helper:
shared/email.ts - Existing footer link:
frontend/src/crm/components/AppFooter.jsx:17