← all posts

· Email · 6 min read

Email on a custom domain without running a mail server

I wanted me@awkto.dev to work. Not a mailbox to log into — just an address on my own domain that quietly lands in the inbox I already read all day. And I did not want to run a mail server to get it.

If you've never run one: receiving mail reliably in 2026 means MX records, a spam filter, TLS, disk for the spool, and — the part that actually hurts — a sending reputation that any residential IP or fresh VPS starts out failing. It's a genuine ongoing job. For one vanity address, it's absurd.

So I don't run one. The entire email stack for this domain is three DNS records and no servers, and it's worth writing down because the pieces are simple once you see how they fit.

The trick: forwarding, not hosting

The service doing the work is Cloudflare Email Routing. It's free, and the important word is routing — it receives mail for your domain and forwards each message to some other inbox you already own. It never stores anything. There's no mailbox on awkto.dev at all; there's nothing to log into. Mail arrives, gets relayed, done.

That single design decision is what makes it free and zero-maintenance. Cloudflare already runs mail-receiving infrastructure at planet scale — accepting a message for your domain and re-sending it to your real inbox is a rounding error for them. You're renting a redirect, not a house.

What's actually in DNS

Because Cloudflare is my DNS provider for the domain anyway, turning this on wrote a handful of records. The two that matter conceptually:

MX records — "where does mail for this domain go?" Mine point at Cloudflare's inbound servers:

awkto.dev.  MX  18 route3.mx.cloudflare.net.
awkto.dev.  MX  26 route2.mx.cloudflare.net.
awkto.dev.  MX  75 route1.mx.cloudflare.net.

Three of them, at different priorities, so there's always a path in if one is busy. Any sending server on the internet that wants to email you@awkto.dev looks this up and hands the message to Cloudflare.

An SPF record — "who is allowed to send as this domain?"

awkto.dev.  TXT  "v=spf1 include:_spf.mx.cloudflare.net ~all"

This is the piece people forget, and it matters because the service forwards. When Cloudflare relays your mail onward, it's sending on behalf of your domain — receiving servers check SPF to decide whether that's legitimate or a spoof. The include: line says "Cloudflare's mail IPs are authorised." Without it, forwarded mail starts landing in spam.

That's the whole substrate. MX says where mail comes in; SPF says who may send out. No server anywhere in that description.

Two rules, one inbox

Inside the routing config there are two forwarding rules, and they represent two different philosophies you can mix:

The catch-all is the quietly great part. I never have to create an address. netflix@awkto.dev, bank@awkto.dev, random-signup-2026@awkto.dev — they all already work and all land in one place. Every service gets its own address for free, which means every service is also its own tracking token: if newsletter@awkto.dev starts getting spam, I know exactly who leaked or sold it, and I can kill that one address without touching anything else.

(One small footgun I left off: sub-addressing — the me+tag@ Gmail-style plus trick — is a separate toggle and it's off by default. With a catch-all you don't need it anyway; just invent a whole new left-hand side.)

Sending is a separate, bolt-on piece

Here's the architectural honesty: Cloudflare Email Routing is inbound only. It forwards mail to you; it will never send mail from me@awkto.dev. That's not a bug, it's the scope — receiving and sending are different jobs on different infrastructure. If all you do is turn on routing and hit reply, the message leaves through whatever inbox the mail landed in, wearing that account's address, not your domain's.

But sending as your domain isn't a big separate project — it bolts straight onto the mailbox you already reply from. Gmail's "Send mail as" lets you add me@awkto.dev as a from-address and push its outbound through any SMTP relay. I point mine at Resend: smtp.resend.com on port 587 with TLS, authenticated by an API key. Now the same Gmail window that receives the forwarded mail sends back out with the right address on it, and the person on the other end never sees the mailbox underneath.

So the full picture is two-way after all: Cloudflare routes inbound → my everyday inbox; that inbox sends outbound → Resend relay → the world. Two services, both on free tiers, no server anywhere, and me@awkto.dev behaves like a real mailbox in both directions.

The one thing sending demands that receiving doesn't is authentication. When a relay sends as your domain, receivers want proof it's allowed to — which means telling DNS about the relay: an SPF include (or a return-path subdomain) plus a DKIM key from whoever relays for you, so the outbound mail is signed and aligned to awkto.dev. Skip it and the mail still goes out, but it leans on the recipient's goodwill instead of cryptographic proof — and stricter servers will notice.

Closing the loop while writing this

Writing this up shook out two loose ends on the outbound side, and rather than leave them as homework I fixed them on the spot. There's a plot twist in it, too: when I went to check my sending setup, the relay didn't actually have awkto.dev registered at all — so "send as me@awkto.dev" had been quietly failing, not sending unauthenticated. The provider was rejecting it outright. Configuring a from-address in your mail client and having the relay accept it are two different things, and I'd only done the first.

So I did the second properly. The relay authentication I described above — the DKIM key plus a return-path subdomain that tell the world the relay may send as awkto.dev — is now published and verified, and a test message that returned a hard rejection an hour earlier sailed straight through. And there's now a DMARC record. DMARC is the policy layer on top of SPF and DKIM: it tells receiving servers what to do when a message fails authentication, and it mails you reports about who's sending as your domain. I've started it at the standard monitoring-only setting (p=none) — it watches and reports without blocking anything — and once the reports confirm my own mail passes cleanly, I'll tighten it to quarantine and then reject. That last tightening is the only thing still outstanding, and it's a deliberate wait, not a loose end.

Was it worth skipping the mail server?

Completely. The scorecard:

For the actual requirement — a professional-looking address on my own domain that both reaches an inbox I already read and can reply from it — a self-hosted mail server would have been all cost and no additional benefit. The right amount of infrastructure was almost none of it. The trick was recognising that "email on my domain" doesn't mean "a mail server on my domain": receiving is a forwarding service, sending is a relay bolted onto the inbox you already have, and neither one is a box you run.