Free email on your own domain with Cloudflare Email Routing and Gmail
Receive mail at you@example.com in your existing Gmail inbox for free, and the options for replying from that address.
Once you own a domain, hello@example.com looks far better on a CV or a contact page than a free webmail
address. A hosted mailbox for it usually costs a few dollars a month per address, and for a personal site that's
hard to justify. All you really want is for mail to reach the inbox you already read.
Cloudflare Email Routing does exactly that, for free. Cloudflare becomes your domain's mail server, accepts messages for the addresses you choose, and forwards them to Gmail. Gmail's Send mail as feature then lets you reply from the same address.
receiving: sender ──▶ MX: route1-3.mx.cloudflare.net ──▶ rule hello@ ──▶ forwarded to you@gmail.com
replying: you@gmail.com ──▶ "Send mail as" hello@example.com ──▶ smtp.gmail.com ──▶ recipient
What you get:
- Free and unlimited addresses.
hello@,jobs@,newsletter@, each forwarding wherever you like. - No mailbox to host. Cloudflare stores nothing. Mail goes straight through to your inbox.
- An optional catch-all that forwards anything sent to
@example.com. - Replies from your domain, sent through your Gmail account, for as long as Gmail supports it.
This guide goes from "my domain has no email" to "mail to hello@ lands in Gmail, and I can answer from it". The last section covers the limits of the free setup, so read it before you print the address on anything.
What you need
- A domain whose DNS is on Cloudflare. If it isn't there yet, Step 1 of the Cloudflare Tunnel guide covers moving the nameservers.
- A Gmail account to receive the mail. Any mailbox works for receiving. The reply steps are Gmail-specific.
- 2-Step Verification turned on for that Google account, for the reply step.
Throughout this post, replace example.com with your domain and you@gmail.com with your mailbox.
Step 1: Add and verify the destination
Cloudflare only forwards to addresses you have proved you own.
- In the Cloudflare dashboard, open your domain and go to Email > Email Routing.
- Under Destination addresses, add
you@gmail.com. - Cloudflare emails that address a verification link, and the address shows as Pending. Click the link. If the email doesn't arrive within a few minutes, check the spam folder.
When the status changes to Verified, the address can be used in rules. Destination addresses belong to your Cloudflare account, so you can reuse a verified one for any other domain you add later.
Step 2: Create the routing rules
Each rule maps one address on your domain to an action.
- Go to Routing rules > Create routing rule.
- For Email pattern, enter the part before the
@(for examplehello) and pick your domain. - For Action, choose Send to an email and select
you@gmail.com. - Save, and repeat for every address you want, for example
mail@.
The Catch-all rule at the top decides what happens to mail for addresses you didn't create. It starts as Drop. Two rules to know:
- Catch-all on means any address works. It's handy for giving every site its own sign-up address
(
shop-name@example.com), but it also forwards every guess a spammer makes. - Catch-all off keeps your inbox clean, and you add addresses as you need them. New rules work immediately, with no DNS change.
Step 3: Point the domain's mail at Cloudflare
Mail finds your domain through its MX records. They have to point at Cloudflare, and nothing else.
-
Remove old mail records first. Many registrars (Namecheap, for example) add default forwarding
MXand SPFTXTrecords when you buy a domain, and they come along when you move DNS to Cloudflare. Cloudflare refuses to add its records while other MX records exist ("Existing non-Cloudflare MX records conflict with Email Routing"). Under DNS > Records, delete the oldMXrecords and the oldv=spf1 ...TXTrecord. If you still receive mail through another provider, stop here, because this replaces it. -
Add Cloudflare's records. Back in Email Routing > Settings, the DNS records section lists what's missing. Click Add missing records. Cloudflare adds and locks these:
Type Name Value MX @route1.mx.cloudflare.net,route2.mx.cloudflare.net,route3.mx.cloudflare.netTXT @v=spf1 include:_spf.mx.cloudflare.net ~all(SPF: who may send for the domain)TXT cf2024-1._domainkeyv=DKIM1; ...(DKIM: the key Cloudflare uses to sign forwarded mail) -
Add a DMARC record. This one tells receiving servers what to do with mail that fails the SPF and DKIM checks. Start in monitor mode, which reports problems but never blocks anything. Under DNS > Records > Add record:
Type Name Content TXT _dmarcv=DMARC1; p=none; rua=mailto:hello@example.com
The Email Routing overview should now show Routing status: Enabled and DNS records: Locked. Locked records can't be edited by accident while you work on other DNS records.
Step 4: Check it works
Ask DNS what the world now sees:
dig +short MX example.com
# route1.mx.cloudflare.net, route2... and route3..., each with a priority number (the numbers vary)
dig +short TXT example.com # "v=spf1 include:_spf.mx.cloudflare.net ~all"
dig +short TXT cf2024-1._domainkey.example.com # "v=DKIM1; h=sha256; k=rsa; p=..."
dig +short TXT _dmarc.example.com # "v=DMARC1; p=none; ..."
Then send a real message from a different account, such as a work address or a friend's, to hello@example.com.
Gmail tends to hide mail you send to yourself, so a test from the same Gmail account can look like it failed when it
didn't. Within a minute or two the message should be in your inbox, and Email Routing > Activity log should list
it as forwarded.
Step 5: Reply from your own address in Gmail
Receiving works. Now teach Gmail to send as hello@example.com.
A date to know. Google has announced that, starting January 2027, Gmail will stop supporting "Send mail as" for addresses that aren't hosted by Google, and setting up new ones may stop working before then. Check Google's help page on sending from a different address for the current status before you rely on this step. Receiving through Email Routing isn't affected. If the option is gone, see "The catch" at the end of this post for alternatives.
Create an app password
Gmail will send your custom address through Google's own SMTP server, logged in as your Gmail account. That login needs an app password, a 16-character code just for this. Your normal Google password is rejected.
- Make sure 2-Step Verification is on in your Google account's security settings.
- Open myaccount.google.com/apppasswords, name the password (for example "Gmail SMTP example.com"), and create it. Copy the code.
The app password must belong to the same Google account you'll put in the username field, so check which account you're signed in to before you create it.
Add the address
-
In Gmail, go to Settings > See all settings > Accounts and Import > Send mail as > Add another email address. A small popup window opens.
-
Enter your name and
hello@example.com. Leave Treat as an alias ticked, and click Next Step. -
Gmail may suggest an SMTP server for your domain. Replace it with Google's own, because Email Routing only receives mail and can't send it. Fill in:
Field Value SMTP Server smtp.gmail.comPort 587Username you@gmail.comPassword the app password Security TLS (recommended) -
Click Add Account. Gmail sends a confirmation email to
hello@example.com. It arrives through the routing you just built, which makes it a free end-to-end test. Click the link, or enter the code in the popup. -
Back under Send mail as, choose Reply from the same address the message was sent to. A reply to mail that came in through
hello@then goes out fromhello@by itself.
When you write a new email, the From field now offers hello@example.com.
The catch: DMARC and sending through Gmail
Receiving through Cloudflare is solid. Sending through Gmail works too, but strict receivers (Proton Mail, for example) may show an authentication warning, even though the message is delivered.
The reason is how receiving servers check a sender. DMARC passes only if the message is vouched for by your domain, which is the one in the From line:
- DKIM: Gmail signs your message, but as
gmail.com, notexample.com. - SPF: the hidden envelope sender is your Gmail address, so SPF checks
gmail.com's servers, not yours.
Both checks pass for gmail.com and neither matches example.com, so DMARC fails. Adding Google's servers to your SPF record doesn't help, because the envelope sender is still gmail.com. Free Gmail can't sign mail for a custom domain.
What to do about it:
- Keep DMARC at
p=nonewhile you send this way. Mail is still delivered. Some receivers show a warning, and some may file it as spam. Never move top=quarantineorp=rejectwith this setup, or your own replies get filtered. - For mail that matters, send through a service that signs for your domain. You verify the domain with it by
adding a few DNS records (its DKIM key and an SPF include), and messages then pass DMARC everywhere. Receiving can
stay on Cloudflare either way. Two routes:
- An SMTP relay with a free tier, such as Resend, Brevo or Amazon SES. Use its SMTP server in a mail client that can send through any server, or in Gmail's Send mail as for as long as Gmail still allows it.
- A mailbox provider that hosts your domain, such as Google Workspace, Proton, Zoho or Fastmail. This is the long-term option, since it doesn't depend on Gmail's Send mail as at all. Most are paid, and they replace Email Routing with their own MX records.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| "Existing non-Cloudflare MX records conflict with Email Routing" | The registrar's old forwarding records are still there | Delete the old MX and SPF TXT records, then click Add missing records again |
| Destination address stays Pending | The verification link wasn't clicked | Check spam, or resend it from Destination addresses |
| Mail to hello@ never arrives | MX doesn't point at Cloudflare, or the rule is off or targets an unverified address | Run dig MX, then check the rule and the Activity log |
| Forwarded mail lands in spam | Missing SPF or DKIM records | Check them with dig, and mark the message as not spam once |
| "Send mail as" fails with error 535, "Username and Password not accepted" | A normal password, or an app password from a different Google account | Create an app password in the account named in the username field. With several accounts signed in, a private window with just that account helps |
| Receivers show an authentication warning on mail you sent | Mail sent through Gmail's SMTP fails DMARC alignment | See "The catch" above |
Recap
- Verify your Gmail address as a destination in Email Routing.
- Create a routing rule for each address. Leave the catch-all off unless you want it.
- Remove the old MX and SPF records, click Add missing records, and add DMARC with
p=none. - Test from another account and check the Activity log.
- To reply, add the address to Gmail's Send mail as with
smtp.gmail.comand an app password, while Gmail still supports it. - Know the DMARC limit, and move to a service that signs for your domain when deliverability matters.
Your domain now receives email at any number of addresses, without a mailbox to pay for or a mail server to run.
Connected
shares a topic with this postDeploy a static site from GitHub to Cloudflare, free
Connect a GitHub repo to Cloudflare, build it on every push, and serve it from the edge on your own domain. No server, no bill, free HTTPS.
Host a website from your own machine with Cloudflare Tunnel
Move your domain to Cloudflare, create a tunnel, and serve apps running on your own hardware without opening a single port.