
Email spoofing usually isn’t a “server got owned” problem. It’s a policy problem. Your domain has no DMARC record (or it has a messy one). That makes it easy for anyone to send mail that looks like it came from you.
This DMARC setup tutorial walks through a safe rollout for a VPS mail setup. You’ll publish SPF and DKIM first. Then you’ll add DMARC with reporting. Finally, you’ll enforce DMARC in stages without cutting off legitimate mail.
These steps work whether you send mail from a VPS (Postfix/Exim), a control panel like cPanel, or a hosted SMTP relay. The DNS work is the same.
If you build mail stacks for clients, get this process right once. Then reuse the checklist on every new domain.
What you’ll set up (and why the order matters)
DMARC sits on top of SPF and DKIM. If SPF or DKIM don’t align with the visible From: domain, DMARC fails. That can happen even when messages “deliver fine” today.
- SPF tells receivers which servers are allowed to send for your domain (MAIL FROM / Return-Path).
- DKIM cryptographically signs messages so receivers can verify they weren’t altered.
- DMARC tells receivers what to do when SPF/DKIM don’t align with your From domain, and where to send reports.
Rollout order in this tutorial:
- Inventory your senders (so you don’t accidentally block your own mail).
- Publish/validate SPF.
- Enable DKIM signing (or verify it’s already enabled).
- Publish DMARC in monitor mode (
p=none) and collect reports. - Move to quarantine/reject in steps, with tight alignment and a fallback plan.
Prerequisites: access, tools, and a quick sender inventory
You’ll need DNS edit access for the domain (registrar or DNS provider). You’ll also need a way to view full headers on a test message.
If mail runs on a VPS, shell access makes validation and troubleshooting much easier.
If you want the admin side to stay predictable, start with a HostMyCode VPS sized for mail workload (CPU for spam filtering, disk for logs and queues).
If you’d rather avoid maintaining Exim/Postfix configs long-term, managed VPS hosting can keep patching and deliverability maintenance from turning into a weekly project.
Step 1: list every place that sends mail as your domain
Before you touch DNS, list every sender that uses your domain in the From address:
- Your VPS mail server (Postfix or Exim/cPanel)
- Website app mail (WordPress, forms, WooCommerce)
- Transactional providers (SMTP relay, helpdesk, CRM)
- Marketing providers (newsletters)
- Any third-party sending on behalf of subdomains (e.g.,
billing.example.com)
If you’re not sure what’s in play, search your inbox for messages from your domain. Note “mailed-by” and “signed-by”. In Gmail, open a message → “Show original”.
Step 2: install basic DNS query tools (VPS)
On Ubuntu/Debian:
sudo apt update
sudo apt install -y dnsutils
On AlmaLinux/Rocky/RHEL:
sudo dnf install -y bind-utils
We’ll use dig to confirm records after you publish them.
Publish SPF correctly (without the usual foot-guns)
SPF is a single TXT record at the root (and optionally on subdomains). Most SPF breakage comes from three issues:
- multiple SPF TXT records
- blowing past the 10-DNS-lookup limit
- forgetting a legitimate sender
Step 3: check whether SPF already exists
dig +short TXT example.com
Look for a string starting with v=spf1.
If you find more than one SPF record, many receivers treat SPF as a “permerror” and effectively fail it.
Step 4: build an SPF record for your real senders
Common building blocks:
ip4:203.0.113.10andip6:...for your VPS public IPsaandmxonly if they truly represent sendersinclude:provider.examplefor SaaS senders (use their documented include)-allonce you’re confident; start with~allif you’re still discovering senders
Example SPF (single VPS IP + a relay include), conservative first pass:
example.com. 300 IN TXT "v=spf1 ip4:203.0.113.10 include:_spf.your-relay.example ~all"
After you’ve checked logs and DMARC reports, tighten to -all:
"v=spf1 ip4:203.0.113.10 include:_spf.your-relay.example -all"
Step 5: validate SPF lookups and propagation
dig +short TXT example.com | tr -d '"'
Operational checklist for SPF:
- Exactly one SPF record per hostname.
- Stay under 10 DNS lookups (each
include,a,mx,ptr,existscan add lookups). - Keep TTL low during rollout (e.g., 300 seconds), then raise later (e.g., 3600–14400).
If you also send from a subdomain (like mail.example.com or news.example.com), publish SPF there too.
DMARC alignment is about the From domain, not necessarily the envelope sender. Decide up front how you want subdomains handled.
Enable DKIM signing (cPanel/WHM and Postfix/OpenDKIM paths)
SPF alone doesn’t carry modern deliverability. DKIM adds an authentication signal that often survives forwarding.
SPF frequently won’t.
Step 6A: cPanel/WHM — confirm DKIM is enabled and published
In WHM:
- Email → Email Authentication
- Make sure DKIM shows as enabled for the domain
- Confirm the suggested DKIM TXT record exists in DNS
If you want the control-panel workflow end-to-end (mail + DNS), use: cPanel mail server setup guide.
Step 6B: Postfix on a VPS — set up OpenDKIM (quick, practical version)
If you run Postfix directly, OpenDKIM is the common choice.
On Ubuntu 24.04/26.04-era builds in 2026, the package names and paths below are stable.
Install packages:
sudo apt update
sudo apt install -y opendkim opendkim-tools postfix
Create a key directory (one domain example):
sudo mkdir -p /etc/opendkim/keys/example.com
sudo chown -R opendkim:opendkim /etc/opendkim/keys
sudo chmod 700 /etc/opendkim/keys/example.com
Generate a 2048-bit key (safe default for 2026):
sudo -u opendkim opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s s1 -v
sudo mv /etc/opendkim/keys/example.com/s1.private /etc/opendkim/keys/example.com/s1.key
Create (or update) these mapping files:
sudo tee /etc/opendkim/KeyTable >/dev/null <<'EOF'
s1._domainkey.example.com example.com:s1:/etc/opendkim/keys/example.com/s1.key
EOF
sudo tee /etc/opendkim/SigningTable >/dev/null <<'EOF'
*@example.com s1._domainkey.example.com
EOF
sudo tee /etc/opendkim/TrustedHosts >/dev/null <<'EOF'
127.0.0.1
localhost
::1
# Add your server IP if needed
EOF
Edit /etc/opendkim.conf (key lines):
Syslog yes
UMask 002
Canonicalization relaxed/simple
Mode sv
SubDomains no
AutoRestart yes
AutoRestartRate 10/1h
Socket inet:12301@localhost
KeyTable /etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
Connect Postfix to OpenDKIM by editing /etc/postfix/main.cf:
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301
Restart services:
sudo systemctl restart opendkim
sudo systemctl restart postfix
sudo systemctl enable opendkim
Step 7: publish the DKIM DNS record
Print the TXT record value from the generated s1.txt file:
sudo cat /etc/opendkim/keys/example.com/s1.txt
You’ll publish it as a TXT record at:
s1._domainkey.example.com→ TXT →v=DKIM1; k=rsa; p=...
Verify it:
dig +short TXT s1._domainkey.example.com
DKIM operational notes:
- Use simple selectors (
s1,s2). You’ll rotate later without downtime. - Don’t reuse DKIM private keys across unrelated domains.
- If you’re planning rotations, keep this handy: DKIM key rotation tutorial.
DMARC setup tutorial: publish a monitor-only policy first
With SPF and DKIM in place, you can publish DMARC.
Start with p=none. This lets you see who’s sending as your domain before you tell receivers to quarantine or reject.
Step 8: create DMARC record with reporting
DMARC is a TXT record at _dmarc.example.com. Start with:
_dmarc.example.com. 300 IN TXT "v=DMARC1; p=none; adkim=s; aspf=s; pct=100; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensics@example.com; fo=1"
Field choices explained (briefly, but practically):
p=none: monitor only.adkim=s,aspf=s: strict alignment. This blocks more spoofing. It also exposes sloppy sender setups. If you rely on lots of third-party senders, start relaxed (r) and tighten later.rua: aggregate reports (XML). Use a dedicated mailbox.ruf: forensic reports (not all receivers send these; privacy policies vary). Optional.fo=1: request failure reports when either SPF or DKIM fails (where supported).
Mailbox warning: DMARC aggregate reports add up fast.
If you manage multiple domains, use per-domain addresses or plus-addressing so you can filter cleanly.
Step 9: verify DMARC in DNS
dig +short TXT _dmarc.example.com
You want exactly one DMARC record. Multiple DMARC records can trigger a “permerror”.
Step 10: send a test message and check authentication results
Send an email from your domain to a Gmail or Outlook mailbox. Then inspect headers.
You’re looking for something like:
Authentication-Results: ...
spf=pass ...
dkim=pass ...
dmarc=pass ...
If DMARC fails, the culprit is usually alignment. It’s usually not “DNS is broken”.
Common causes:
- From domain is
example.combut DKIM signs asmail.example.net(misalignment). - SPF passes for the server’s HELO domain but not for the envelope sender domain.
- A third-party service sends with your From domain, but you didn’t add their SPF include and/or DKIM setup.
Move from monitor to enforcement (without breaking customer mail)
Leave monitor mode running long enough to get a real picture.
Busy domains usually show clear patterns within 24–72 hours. Quiet domains may need closer to a week.
Step 11: fix the “unknown senders” before enforcing
As reports arrive, focus on legitimate sources that fail SPF/DKIM.
For each sender, pick one path:
- Add it to SPF (carefully, avoiding lookup explosion)
- Configure it to DKIM-sign with your domain (preferred)
- Move that sender to a subdomain and set separate DMARC there
If you run cPanel mail, keep reputation issues from piling up. Set PTR/rDNS and match it to your mail hostname.
That’s not DMARC, but it affects inbox placement and hard rejections.
Use: rDNS setup guide.
Step 12: switch to quarantine gradually
Update DMARC to quarantine a small percentage first:
"v=DMARC1; p=quarantine; pct=25; adkim=s; aspf=s; rua=mailto:dmarc-reports@example.com"
Then move to pct=50, then pct=100 over several days.
If you see unexpected failures, roll back to p=none while you fix SPF/DKIM alignment.
Step 13: move to reject once you’re stable
Final enforcement (typical end state):
"v=DMARC1; p=reject; pct=100; adkim=s; aspf=s; rua=mailto:dmarc-reports@example.com"
Practical tip for resellers: strict alignment can turn into support tickets. This happens when clients send through random SMTP plugins.
Standardize outbound mail (server mail or a relay). Document the standard. Then enforce it.
Common troubleshooting: DMARC fails even though SPF and DKIM “pass”
This is common. A raw “pass” doesn’t guarantee DMARC passes.
DMARC requires alignment with the From domain.
Check 1: DKIM d= domain matches your From domain
In headers, find:
DKIM-Signature: ... d=example.com; s=s1; ...
If d= isn’t your From domain (or an aligned domain under relaxed rules), DMARC fails even if DKIM technically passes.
Check 2: SPF passes for the envelope sender domain
SPF is evaluated against the Return-Path / MAIL FROM domain, not the visible From.
DMARC then checks whether that SPF domain aligns with the From domain (based on aspf).
Check 3: forwarding and mailing lists
Forwarding often breaks SPF because the forwarder’s IP isn’t in your SPF record.
DKIM usually survives if the forwarder doesn’t modify the message.
Mailing lists frequently rewrite headers or the body. That can break DKIM.
If your users rely on mailing lists, start with relaxed alignment (adkim=r; aspf=r). Watch reports before switching to strict.
Check 4: DNS split-brain or wrong nameservers
Confirm you’re editing the same DNS zone the domain actually delegates to.
A lot of “DMARC doesn’t work” cases come down to updating records in the wrong provider dashboard.
If you run your own DNS on a hosting server, double-check delegation and glue records. Pair this with: cPanel nameserver setup guide.
Hardening checklist for a mail VPS (small changes, big impact)
DMARC helps receivers trust your mail. Your server still needs basic hygiene. Without it, you’ll run into rate limits, filtering, and blacklists.
- Open only required ports (25, 465/587 if you offer submission, 143/993 for IMAP if hosted). Audit before tightening: firewall audit tutorial.
- TLS certificates for SMTP/IMAP: keep them valid and auto-renewing. Use: SSL certificate deployment tutorial.
- Correct hostname + rDNS: match PTR to your mail hostname and make sure forward DNS matches back.
- Log visibility: don’t troubleshoot deliverability blind. Set up basic monitoring and alerts.
If you’re rolling out SPF/DKIM/DMARC for one domain or fifty, stability matters more than clever config. Run it on a HostMyCode VPS, or hand off patching and mail stack upkeep to managed VPS hosting so you can spend your time on deliverability and client ops—not queue triage and TLS renewals.
FAQ: DMARC rollout questions you’ll hit in real hosting work
Should I start DMARC with p=none or go straight to reject?
Start with p=none unless you’re 100% sure all legitimate mail is SPF/DKIM-aligned. Monitor reports, then enforce in steps.
Do I need DKIM if SPF already passes?
Yes. SPF breaks on forwarding and doesn’t protect message integrity. DKIM gives a second independent signal, and DMARC can pass via DKIM even when SPF fails.
What’s a safe DMARC policy for a small business domain?
A common path is p=none for monitoring, then p=quarantine with pct=25, then pct=100, then p=reject once reports are clean.
Can I use different DMARC policies for subdomains?
Yes. Either publish DMARC at the subdomain’s _dmarc.sub.example.com, or use sp= in the organizational DMARC record to set a default for subdomains.
My DMARC reports show lots of unknown sources. What should I do first?
Confirm they’re actually sending mail with your From domain (not just failing attempts), then fix alignment: add the sender to SPF and/or configure DKIM signing for your domain. Don’t jump to reject until the legitimate sources are clean.
Summary: a repeatable DMARC rollout you can support
DMARC isn’t a single TXT record you toss into DNS and forget. Treat it like a controlled change.
Inventory senders, validate SPF, enable DKIM, publish DMARC in monitor mode, then enforce using real report data.
If you want this to stay calm across domains and client accounts, run mail on infrastructure you can depend on. HostMyCode gives you a clean base with HostMyCode VPS options and operational help through managed VPS hosting when you’d rather not babysit mail queues and certificate renewals.