Building domain email with Azure DNS and Zoho Mail
A practical build note for connecting a custom domain to Zoho Mail while managing MX, SPF, DKIM, and DMARC records through Azure DNS and Terraform.
- Azure DNS
- Public zone
- Zoho Mail
- Mail Lite
- Terraform
- DNS records
On this page
Domain email looks small until the site becomes public. Once a project has a contact page, privacy policy, advertising review, or correction channel, a personal mailbox is no longer enough. The goal for this build was to attach a real domain email address to hwmoon.com while keeping DNS changes reproducible.
The final shape is intentionally boring:
Custom domain
-> Azure DNS public zone
-> Zoho Mail MX records
-> SPF, DKIM, DMARC TXT records
-> contact mailbox
The important choice was not only “use Zoho Mail.” The important choice was to keep the DNS state in Azure DNS and manage it with Terraform so that mail routing can be audited and rebuilt later.
Why This Was Needed
Public projects need a stable contact address. The address is used for operational questions, privacy requests, advertising review, partnership mail, and correction reports. A domain address also makes the site look like a maintained property rather than a temporary page.
For this project, the requirements were:
| Requirement | Decision |
|---|---|
| Custom mailbox | Zoho Mail Lite |
| DNS authority | Azure DNS |
| Mail receiving | Zoho MX |
| Sender authentication | SPF, DKIM, DMARC |
| Change management | Terraform |
| Public contact | contact@hwmoon.com |
Google Workspace would also work, but it is heavier than necessary for a single project mailbox. Zoho Mail was a better starting point because it supports custom domain mail and standard authentication records without forcing a large collaboration suite into the stack.
DNS Ownership
The domain is managed in an Azure DNS public zone. That keeps website, verification, and mail records in one place.
Conceptually, the root zone owns these record families:
@ TXT site verification, SPF
@ MX Zoho inbound mail servers
zmail._domainkey TXT DKIM public key
_dmarc TXT DMARC policy
The exact values come from Zoho and the current DNS environment, so the public article avoids publishing real verification tokens. The reusable part is the shape.
SPF
SPF tells receiving mail systems which senders are allowed to send mail for the domain. For Zoho, the record is placed on the root domain as a TXT value.
v=spf1 include:zohomail.com ~all
This is not a complete anti-spam solution, but it is the baseline. Without SPF, even legitimate outbound mail can be treated as suspicious.
DKIM
DKIM signs outbound mail with a private key held by the mail provider. The public key is published in DNS.
Zoho provides a selector and a TXT value. The DNS name usually looks like this:
selector._domainkey.example.com
The selector value is provider-generated, so the build process should treat it as configuration rather than hard-coded knowledge.
DMARC
DMARC tells receivers what to do when SPF or DKIM alignment fails. For a new domain, the safest rollout is to start with monitoring or a soft policy and tighten it later.
Example shape:
v=DMARC1; p=none; rua=mailto:contact@example.com
After mail flow is confirmed, the policy can move toward quarantine or reject. Jumping directly to a strict policy is risky if SPF or DKIM has not been observed in real traffic.
Terraform Shape
The Terraform model should keep record ownership explicit. A simplified record map looks like this:
txt_records = {
"@" = {
ttl = 300
records = [
"google-site-verification=REPLACE_WITH_VALUE",
"zoho-verification=REPLACE_WITH_VALUE",
"v=spf1 include:zohomail.com ~all"
]
}
"_dmarc" = {
ttl = 300
records = [
"v=DMARC1; p=none; rua=mailto:contact@example.com"
]
}
}
The real module separates MX records from TXT records, but the operating principle is the same: DNS should be readable as infrastructure state, not as a set of manual portal clicks.
Verification
The two useful checks are DNS propagation and provider verification.
dig MX hwmoon.com @8.8.8.8 +short
dig TXT hwmoon.com @8.8.8.8 +short
dig TXT _dmarc.hwmoon.com @8.8.8.8 +short
Then the Zoho admin screen confirms whether the domain, MX, SPF, and DKIM records are accepted.
The operational lesson is simple: email setup is not a one-time wizard. It is part of the publishing platform. When the site is used for AdSense, privacy, or business contact, mail reliability becomes part of production readiness.
Operating Policy
For future domain email work:
- manage DNS records in Terraform
- keep provider-generated tokens out of public docs
- start DMARC conservatively
- verify with multiple public resolvers
- keep
contact@alive before enabling public policy pages or advertising review
This keeps the mailbox boring in the best way: predictable, rebuildable, and easy to explain later.
Series
Publisher Infrastructure
Part 1 of 8. This series collects related build notes so the context is easier to follow later.
- 1. Building domain email with Azure DNS and Zoho Mail
- 2. Running an Azure DevOps self-hosted agent on Synology NAS
- 3. Why a successful Static Web Apps pipeline still returned 404
- 4. Using Azure Repos as the primary source and GitHub as a backup mirror
- 5. Automating NAS agent operations with Slack-based AIOps
- 6. Preventing another news.hwmoon.com article publishing outage
- 7. AdSense readiness operations for news.hwmoon.com
- 8. Fixing news.hwmoon.com deployment outages with self-healing agent healthchecks