Configure SPF, DKIM, and DMARC on a mail VPS

You just moved to a mail VPS, sent your first campaign, and half of it went to spam. That is not bad luck. That is missing SPF, DKIM, and DMARC records, the three DNS-based authentication methods every receiving server checks before it decides whether your email is legitimate. This guide walks you through configuring all three on a self-hosted mail server, with real commands and verification steps for each record.
Estimate: 30-45 minutes if your DNS is at a normal registrar. Longer if your domain has existing TXT records you need to merge carefully.
Prerequisites
- A Linux VPS with a mail server already installed and sending mail. This guide uses Postfix and OpenDKIM on Ubuntu 24.04, but the DNS records work for any MTA.
- Full control of your domain's DNS zone, meaning you can add and edit TXT records.
- A dedicated IPv4 for your mail server, because SPF and reverse DNS (rDNS) both tie back to a specific IP address. If you are setting this up from scratch, rent a Linux VPS with a clean IP and configure rDNS first.
- Root or sudo access to the server.
Why SPF, DKIM, and DMARC matter in 2026
Every mail server that receives your message runs three checks before deciding what to do with it. SPF asks: is this sending IP allowed to send for this domain? DKIM asks: is the message signature cryptographically valid and does the public key in DNS match the private key on the server? DMARC asks: when SPF and DKIM both fail, what should the receiver do with the message?
A missing or misconfigured record is an instant spam folder trip. A 2025 industry report from Valimail found that domains with all three records published in p=reject mode see deliverability rates above 95% for legitimate mail, while domains with no authentication at all see acceptance rates below 70%. The gap is entirely avoidable.
There is a second reason these records matter: domain spoofing. Without DMARC, anyone can send mail that looks like it comes from your domain and receivers have no policy to fall back on. Configuring these three records is not just about getting your own mail delivered, it is about preventing your domain from being used against your customers.
越南 VPS 邮件服务器需要 SPF、DKIM 和 DMARC 才能避免进入垃圾邮件文件夹。
A mail VPS in Vietnam needs SPF, DKIM, and DMARC to keep email out of the spam folder.
Step 1 - Publish the SPF record
SPF (Sender Policy Framework) is a TXT record at the root of your domain that lists which servers are allowed to send mail for it. The receiver looks up this record, checks the envelope sender address, and compares the connecting IP against the list.
Start by checking if you already have an SPF record, because you can only have one and trying to add a second one breaks both:
dig TXT example.com +short
If the output shows v=spf1 ..., you already have one and need to edit it. If you see other TXT records like verification strings for Google or Facebook, leave them alone. If there is no SPF record, create one.
The basic record for a single mail server looks like this:
v=spf1 ip4:203.0.113.10 -all
Change the IP to your mail server's actual IPv4 address. The -all at the end means "reject everything not listed here", which is the strictest and recommended setting. Some older guides suggest ~all (soft fail), but in 2026 there is no reason to use it for a domain that only sends from known servers.
If you also send mail through a third-party service like Google Workspace or Mailchimp, include their SPF includes:
v=spf1 ip4:203.0.113.10 include:_spf.google.com include:servers.mcsv.net -all
The record must be published as a TXT record, not an A record. Some DNS providers try to be helpful and parse SPF as a special type, which breaks it. Always add it as TXT.
Verify:
dig TXT example.com +short
# Expected output contains: "v=spf1 ip4:203.0.113.10 -all"
SPF has a hard limit of 10 DNS lookups per record. Each include: counts as one lookup, and if you exceed 10, receivers silently skip the SPF check entirely. Check your record with spf-tools or an online SPF validator to confirm you are under the limit.
Step 2 - Set up and configure OpenDKIM
DKIM (DomainKeys Identified Mail) uses a public/private key pair. The private key stays on your mail server and signs every outgoing message. The public key is published in DNS. Receivers fetch the public key and verify the signature.
Install and configure OpenDKIM on Ubuntu 24.04:
sudo apt update
sudo apt install opendkim opendkim-tools
Edit the main configuration file:
sudo nano /etc/opendkim.conf
Make sure these lines are present and uncommented:
# Canonicalization: relaxed on both sides handles forwarding better
Canonicalization relaxed/relaxed
# The socket Postfix will use to send messages to OpenDKIM
Socket local:/var/spool/postfix/opendkim/opendkim.sock
# The selector we will use for this key
Selector mail
# The domain key table maps domains to key files
KeyTable /etc/opendkim/key.table
SigningTable refile:/etc/opendkim/signing.table
InternalHosts /etc/opendkim/trusted.hosts
Create the directory structure and generate a key pair:
sudo mkdir -p /etc/opendkim/keys/example.com
sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s mail -v
sudo chown -R opendkim:opendkim /etc/opendkim
This creates two files: mail.private (the private key) and mail.txt (the DNS record you will publish). The selector mail is a label that lets you rotate keys later without changing the DNS record structure, just the value.
Set up the table files:
sudo nano /etc/opendkim/key.table
# Add a line mapping the selector and domain to the key file
mail._domainkey.example.com example.com:mail:/etc/opendkim/keys/example.com/mail.private
sudo nano /etc/opendkim/signing.table
# Add a line telling OpenDKIM which domain to sign
*@example.com example.com
sudo nano /etc/opendkim/trusted.hosts
# Add localhost so internal mail is not signed
127.0.0.1
localhost
# Add your domain so mail from local users is signed
example.com
Now connect Postfix to OpenDKIM. Add these lines to /etc/postfix/main.cf:
sudo postconf -e 'milter_default_action = accept'
sudo postconf -e 'milter_protocol = 6'
sudo postconf -e 'smtpd_milters = local:/opendkim/opendkim.sock'
sudo postconf -e 'non_smtpd_milters = local:/opendkim/opendkim.sock'
Restart both services:
sudo systemctl restart opendkim
sudo systemctl restart postfix
Verify the service is running and see if it actually signs:
sudo systemctl status opendkim
# Expected: active (running)
sudo tail -f /var/log/mail.log
Send a test email to a mailbox you control and watch the log for a line containing dkim=pass or dkim=sign. A very common failure is a socket path mismatch between Postfix and OpenDKIM. If you see milter connection failure in the mail log, the socket paths do not match, or the Postfix chroot does not expose the socket file.
Step 3 - Publish the DKIM public key
The file /etc/opendkim/keys/example.com/mail.txt contains the DNS record. Its content looks like this:
mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..." )
Create a TXT record in your DNS with the hostname mail._domainkey and paste the entire p= value as the content. Some DNS providers accept the quoted format directly, others want just the v=DKIM1; ... string.
Verify the DNS record is live and correctly formatted:
dig TXT mail._domainkey.example.com +short
# Expected output: "v=DKIM1; h=sha256; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
If you use an SMTP VPS with a clean IP as your sending infrastructure, do not skip this step. A clean IP without DKIM still lands in spam, the authentication records are what build reputation.
DKIM keys expire or get compromised, so pick a selector that lets you rotate cleanly. The selector mail is fine. A selector like 2026 makes it obvious when it was created.
Step 4 - Create the DMARC policy
DMARC (Domain-based Message Authentication, Reporting, and Conformance) tells receivers what to do when SPF and DKIM both fail. It also generates aggregate reports that show you who is sending mail for your domain.
Create a TXT record with the hostname _dmarc and a policy that starts in monitoring mode:
v=DMARC1; p=none; rua=mailto:[email protected]; fo=1
Break down what each part does:
| Tag | Value | Meaning |
|---|---|---|
| v | DMARC1 | Version identifier, always this value |
| p | none | Policy: none = monitor only, quarantine = send to spam, reject = bounce outright |
| rua | mailto:[email protected] | Aggregate report destination. Reports come daily from major providers |
| fo | 1 | Generate failure reports when any authentication check fails |
Start with p=none for two weeks. The aggregate reports tell you which legitimate senders are missing SPF or DKIM alignment. When the reports show no unexpected failures, tighten the policy:
v=DMARC1; p=quarantine; rua=mailto:[email protected]; fo=1
After another two weeks with no false positives, move to the strongest policy:
v=DMARC1; p=reject; rua=mailto:[email protected]; fo=1
Verify the DMARC record:
dig TXT _dmarc.example.com +short
# Expected output: "v=DMARC1; p=quarantine; rua=mailto:[email protected]; fo=1"
Important detail: DMARC requires what is called alignment. For DMARC to pass, the domain in the From header must match the domain in either the SPF envelope sender or the DKIM signature d= tag. If you send through a subdomain like mail.example.com while the From header says @example.com, strict alignment fails. Use rua reports to catch these cases before you tighten the policy.
Why DMARC alignment fails and what to do
The most common reason DMARC fails even when SPF and DKIM both pass on their own is a subdomain mismatch. Your SPF record may authorize the sending server and your DKIM signature may be valid, but if the From header domain and the authenticated domain differ, DMARC checks alignment and fails the whole message.
The fix has two parts. First, make sure the From header always uses the apex domain. Second, check your DKIM signatures cover the actual From domain:
# Check which domain a message was signed for
grep -r "SigningTable" /etc/opendkim/
# The signing table should include an entry like this for every sender domain
*@example.com example.com
The second common failure is a DNS record that has not fully propagated. TXT records for authentication take anywhere from minutes to 48 hours depending on your DNS provider's TTL. Do not panic and redo everything if verification fails immediately after you publish.
Step 5 - Verify all three records together
Publishing the records is half the job. The other half is proving they work end to end. Use these two tools:
# Local DNS verification
dig TXT example.com +short
dig TXT mail._domainkey.example.com +short
dig TXT _dmarc.example.com +short
# Test authe.ntication with a dedicated tool
swaks --to [email protected] --from [email protected] --server localhost
Send a test message to [email protected], a free service that replies with a full authentication report. The reply shows each check: SPF, DKIM, and DMARC with pass or fail status. If the report shows a pass on all three, your configuration is complete.
Also add the autoreply address from your rua tag to a mailbox you actually read. The daily aggregate reports from Google, Yahoo, and Microsoft are plain XML, but they are the ground truth for who is sending mail using your domain.
Which VPS setup pairs well with these records
These authentication records work on any mail server, but they are only as effective as the IP reputation behind them. A VPS with a dedicated IPv4 in Vietnam gives you a clean starting reputation that you control, no shared-SMTP neighbors tanking your sender score. If your use case is transactional mail or small campaigns, a Linux VPS with a dedicated IPv4 plus Postfix and these records is a solid, low-cost setup. If you are doing volume sending, an SMTP VPS with a warm IP and the same SPF/DKIM/DMARC records keeps you out of shared blacklists.
Your receiving server matters more than you might think. Check the rDNS (PTR record) resolves to a hostname that matches the HELO your mail server sends. This is not a formal part of SPF, DKIM, or DMARC, but nearly every receiving server checks it and rejects mail with missing or mismatched rDNS.
FAQ
What is the difference between SPF, DKIM, and DMARC?
SPF authorizes which IP addresses can send mail for your domain. DKIM provides a cryptographic signature that proves a message was not tampered with. DMARC tells receivers what to do when SPF and DKIM both fail, and it requires the From domain to align with the authenticated domain.
How long does it take for DNS records to propagate after I publish them?
Usually minutes, but older caching DNS resolvers may hold TXT records for up to 48 hours. Lower the TTL on the record before publishing to speed up propagation. Always verify with dig against a public resolver like dig @8.8.8.8 TXT example.com.
Why is my email still going to spam even with all three records?
Check your rDNS PTR record matches your server's HELO hostname, your sending IP is not on any blacklist, and your email content does not trip spam filters. Authentication records prevent domain-based rejection, but spam filters still score content and sending behavior.
Should I use p=none, p=quarantine, or p=reject for DMARC?
Start with p=none to collect reports and confirm legitimate senders pass authentication. Move to p=quarantine after two weeks of clean reports, then p=reject after another two weeks with no false positives. Going straight to p=reject risks blocking legitimate mail from sources you forgot.
Do I need rDNS separately from SPF and DKIM?
Yes, even though it is not a formal authentication record. Nearly every receiving mail server checks that the connecting IP's PTR record matches the hostname your server uses in its HELO greeting. Mismatched rDNS is one of the most common reasons mail gets rejected even when SPF, DKIM, and DMARC all pass.
Related articles
- SPF, DKIM and DMARC on a self-hosted SMTP server
- Set up rDNS on an SMTP VPS in 2026
- Warming up a new sending IP, a realistic 30 day schedule
- Why shared SMTP relays hurt deliverability once you scale
邮件VPS的SPF、DKIM、DMARC配置要点
在邮件VPS上配置SPF、DKIM和DMARC是确保邮件不进入垃圾箱的关键。SPF记录指定允许发送邮件的IP,DKIM使用公钥私钥对签名邮件,DMARC则定义当SPF和DKIM都失败时的处理策略。建议先用p=none收集报告,确认正常发信后逐步升级到p=reject。务必同时配置rDNS反向解析,否则即使三项认证全部通过,部分收件服务器仍会拒绝邮件。


