How to Properly Configure SPF, DKIM, and DMARC for Your Mail Server (Postfix + Gmail Deliverability)
Gmail has strict requirements for accepting bulk email. If you’re running your own mail server (e.g. Postfix), follow this guide to configure everything according to Google's standards and improve your deliverability.
π§ 1. DNS Setup (A, PTR, SPF, DKIM, DMARC)
- A-record: Ensure each mail hostname resolves to the correct IP.
- PTR (rDNS): The IP address must reverse-resolve to the same domain as your HELO/EHLO hostname.
- SPF: Example record:
vindazo.be. IN TXT "v=spf1 ip4:144.76.216.108 ip4:144.76.216.109 ip4:148.251.233.101 -all"
- DKIM: Generate a key using
opendkim-genkey
and publish it as a TXT record:alert._domainkey.vindazo.be. IN TXT "v=DKIM1; k=rsa; p=MIIBI...QAB"
- DMARC: Start with:
_dmarc.vindazo.be. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@vindazo.be; fo=1"
π 2. Postfix and OpenDKIM Setup
Configure Postfix to use OpenDKIM:
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:12301
non_smtpd_milters = inet:localhost:12301
In /etc/opendkim.conf
:
Domain vindazo.be
KeyFile /etc/opendkim/keys/vindazo.be/alert.private
Selector alert
Canonicalization relaxed/relaxed
Mode sv
π 3. Testing Results from SpamAssassin
Here’s a real-world test score example:
DKIM_VALID 0.1 ✅ DKIM is valid SPF_PASS 0.001 ✅ SPF matches sender SPF_HELO_NONE -0.001 ⚠️ HELO domain missing SPF RCVD_IN_RP_SAFE 2.0 ✅ Whitelisted relay T_REMOTE_IMAGE -0.01 ⚠️ External images present
To fix SPF_HELO_NONE
, publish this record for the HELO domain (e.g. alert.vindazo.be):
alert.vindazo.be. IN TXT "v=spf1 ip4:144.76.216.109 -all"
π¬ 4. DKIM Validation Result
Example valid DKIM signature:
v=1; a=rsa-sha256; c=simple/simple; d=vindazo.be; s=alert;
bh=EnX/...; h=Subject:From:To:Date;
b=j7zdLO3Qk5R8C/oqBSEjY...
Validated using:
opendkim-testkey -d vindazo.be -s alert -vvv
- Mail-Tester.com
π 5. Recommended DMARC Policy Progression
- Start with:
v=DMARC1; p=none; rua=mailto:dmarc@vindazo.be; fo=1
- After verifying reports, move to:
v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@vindazo.be; fo=1
- Eventually:
v=DMARC1; p=reject; rua=mailto:dmarc@vindazo.be; fo=1
π§ 6. Useful Tools
- Mail Tester – spam score
- Google DIG Tool
- MXToolbox – SPF/DKIM checks
- DMARCian DKIM Inspector
- Google Sender Guidelines
With SPF, DKIM, and DMARC correctly configured, and PTR/HELO alignment in place, your mail server is fully compliant with Gmail's bulk sender guidelines. Always test changes using live Gmail inboxes or mail-tester, and monitor your DMARC reports regularly.
Google RequirmentsFAQ
Need help automating this setup for multiple servers? Use monitoring tools, scripts, or managed platforms to simplify operations.
✅ Configure Postfix and OpenDKIM with Multiple Domains and IPs
This guide walks you through configuring Postfix and OpenDKIM for multiple domains using separate IP addresses and HELO names.
π Domains and IP Mapping
Domain | IP | HELO Hostname |
---|---|---|
example1.com | 192.0.2.10 | mail.example1.com |
example2.net | 192.0.2.20 | mail.example2.net |
example3.org | 192.0.2.30 | mail.example3.org |
1️⃣ Install Required Packages
apt update
apt install postfix opendkim opendkim-tools
2️⃣ OpenDKIM Configuration
/etc/opendkim.conf
Syslog yes
UMask 002
Socket inet:8891@localhost
UserID opendkim:opendkim
PidFile /var/run/opendkim/opendkim.pid
Mode sv
Canonicalization relaxed/relaxed
OversignHeaders From
TrustAnchorFile /usr/share/dns/root.key
DNSTimeout 5
SignatureAlgorithm rsa-sha256
KeyTable /etc/opendkim/KeyTable
SigningTable /etc/opendkim/SigningTable
ExternalIgnoreList /etc/opendkim/TrustedHosts
InternalHosts /etc/opendkim/TrustedHosts
/etc/opendkim/TrustedHosts
127.0.0.1
localhost
192.0.2.10
192.0.2.20
192.0.2.30
/etc/opendkim/SigningTable
info@example1.com default._domainkey.example1.com
info@example2.net default._domainkey.example2.net
info@example3.org default._domainkey.example3.org
/etc/opendkim/KeyTable
default._domainkey.example1.com example1.com:default:/etc/opendkim/keys/example1.com/default.private
default._domainkey.example2.net example2.net:default:/etc/opendkim/keys/example2.net/default.private
default._domainkey.example3.org example3.org:default:/etc/opendkim/keys/example3.org/default.private
Generate DKIM Keys
mkdir -p /etc/opendkim/keys/example1.com
opendkim-genkey -D /etc/opendkim/keys/example1.com/ -d example1.com -s default
3️⃣ Postfix Configuration
/etc/postfix/main.cf
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
sender_dependent_default_transport_maps = regexp:/etc/postfix/sdd_transport_maps.regexp
/etc/postfix/sdd_transport_maps.regexp
/info@example1\.com$/ example1_transport
/info@example2\.net$/ example2_transport
/info@example3\.org$/ example3_transport
/etc/postfix/master.cf
example1_transport unix - - n - - smtp
-o smtp_bind_address=192.0.2.10
-o smtp_helo_name=mail.example1.com
example2_transport unix - - n - - smtp
-o smtp_bind_address=192.0.2.20
-o smtp_helo_name=mail.example2.net
example3_transport unix - - n - - smtp
-o smtp_bind_address=192.0.2.30
-o smtp_helo_name=mail.example3.org
4️⃣ Restart Services
systemctl restart opendkim
systemctl restart postfix
5️⃣ Testing
Use opendkim-testkey
and swaks
to verify configuration:
opendkim-testkey -d example1.com -s default -vvv
swaks --from info@example1.com --to test@example.net --server 127.0.0.1
✅ Final Checklist
- DKIM key published in DNS
- Matching SigningTable and KeyTable
- Correct file permissions
- Postfix master.cf contains right IPs and HELOs
- SPF & DMARC configured correctly
Swaks Test Script
#!/bin/bash # Variables FROM="info@mydomain.nl" TO="test-9op06vehp@srv1.mail-tester.com" HELO="mail.mydomain.nl" SERVER="127.0.0.1" SUBJECT="DKIM/SPF Test via Swaks" BODY="This is a test message sent from Swaks to check DKIM, SPF and HELO." # Send email via Swaks swaks --from "$FROM" \ --to "$TO" \ --server "$SERVER" \ --data "Subject: $SUBJECT\n\n$BODY" \ --h-Subject "$SUBJECT" \ --header "From: $FROM" \ --header "To: $TO" \ --ehlo "$HELO" echo "Test message sent to $TO"
Comments
Post a Comment