Skip to main content
Back to Category

SPF, DKIM and DMARC Configuration Guide

Complete guide to configuring SPF records, DKIM signing, DMARC policies, DNS records, and testing tools to improve email deliverability and security.

Read time: 15 min Email
spfdkimdmarcemaildnssecuritymail

Table of Contents

Introduction

Email deliverability and trustworthiness depend on proper DNS configuration. SPF (Sender Policy Framework), DKIM (DomainKeys Identified Mail), and DMARC (Domain-based Message Authentication, Reporting & Conformance) protocols prevent your emails from landing in spam folders and protect against domain spoofing.

In this guide, we will configure SPF, DKIM, and DMARC records step by step to secure your email sending infrastructure on your REXE server.

What is SPF (Sender Policy Framework)?

SPF is a DNS record that defines which servers are authorized to send emails on behalf of your domain. The receiving mail server checks whether the incoming email originates from an IP address specified in the SPF record.

Creating an SPF Record

Add it as a TXT record in your DNS management panel:

hljs dns
@ IN TXT "v=spf1 ip4:SERVER_IP_ADDRESS -all"

If you use multiple servers:

hljs dns
@ IN TXT "v=spf1 ip4:IP_ADDRESS_1 ip4:IP_ADDRESS_2 include:_spf.google.com -all"

SPF Mechanisms

MechanismDescription
ip4:Specific IPv4 address or CIDR block
ip6:Specific IPv6 address or CIDR block
include:Include another domain's SPF record
aAllow the IP in the domain's A record
mxAllow the servers in the domain's MX record
allPolicy for all other sources

SPF Qualifiers

+all  → Pass (allow all — NOT RECOMMENDED)
~all  → SoftFail (mark unauthorized but don't reject)
-all  → Fail (reject unauthorized — RECOMMENDED)
?all  → Neutral (no check)

Always use -all or at least ~all in your SPF record. Using +all leaves your domain open to spoofing.

Testing the SPF Record

hljs bash
# Query SPF record with dig
dig TXT example.com +short

# Query with nslookup
nslookup -type=TXT example.com

Online tools:

What is DKIM (DomainKeys Identified Mail)?

DKIM is a protocol that adds a digital signature to outgoing emails, verifying that the message has not been altered during transit. The sending server signs with a private key, and the receiving server verifies using the public key in DNS.

Generating a DKIM Key Pair

Create a 2048-bit RSA key pair with OpenSSL:

hljs bash
# Generate private key
openssl genrsa -out dkim_private.pem 2048

# Extract public key
openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem

# Convert public key to DNS format
cat dkim_public.pem | grep -v '^-' | tr -d '\n'

DKIM Configuration with Postfix (OpenDKIM)

Install OpenDKIM:

hljs bash
sudo apt update
sudo apt install opendkim opendkim-tools -y

Generate keys:

hljs bash
sudo mkdir -p /etc/opendkim/keys/example.com
sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s default -v
sudo chown -R opendkim:opendkim /etc/opendkim

OpenDKIM configuration file (/etc/opendkim.conf):

hljs conf
AutoRestart             Yes
AutoRestartRate         10/1h
SyslogSuccess           Yes
LogWhy                  Yes

Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no

OversignHeaders         From

KeyTable                refile:/etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table
ExternalIgnoreList      /etc/opendkim/trusted.hosts
InternalHosts           /etc/opendkim/trusted.hosts

Socket                  inet:8891@localhost

Key table file (/etc/opendkim/key.table):

default._domainkey.example.com example.com:default:/etc/opendkim/keys/example.com/default.private

Signing table file (/etc/opendkim/signing.table):

*@example.com default._domainkey.example.com

Trusted hosts file (/etc/opendkim/trusted.hosts):

127.0.0.1
localhost
example.com

Adding the DKIM DNS Record

Add the generated public key as a TXT record in DNS:

hljs dns
default._domainkey IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhki...(PUBLIC_KEY)..."

DKIM keys should be 2048-bit. 1024-bit keys are no longer considered secure.

Postfix Integration

Add to Postfix configuration (/etc/postfix/main.cf):

hljs conf
milter_protocol = 6
milter_default_action = accept
smtpd_milters = inet:localhost:8891
non_smtpd_milters = $smtpd_milters

Restart services:

hljs bash
sudo systemctl restart opendkim
sudo systemctl restart postfix

Testing the DKIM Record

hljs bash
# Query DKIM record from DNS
dig TXT default._domainkey.example.com +short

# OpenDKIM test tool
opendkim-testkey -d example.com -s default -vvv

What is DMARC (Domain-based Message Authentication)?

DMARC combines SPF and DKIM results, giving domain owners the ability to set email authentication policies and receive reports. The receiving server acts according to the DMARC policy for emails that fail SPF or DKIM verification.

Creating a DMARC Record

Add as a TXT record in DNS:

hljs dns
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; fo=1; adkim=r; aspf=r; pct=100"

DMARC Policy Levels

PolicyDescriptionUsage
p=noneReport only, no actionFirst stage — monitoring
p=quarantineSend to spam folderMedium protection
p=rejectReject the email entirelyFull protection

DMARC Tags

TagDescriptionExample
vVersion (required)v=DMARC1
pPolicy (required)p=reject
ruaAggregate report addressrua=mailto:report@domain.com
rufForensic report addressruf=mailto:forensic@domain.com
foFailure reporting optionfo=1 (on every failure)
adkimDKIM alignment moder (relaxed) or s (strict)
aspfSPF alignment moder (relaxed) or s (strict)
pctPolicy application percentagepct=100
spSubdomain policysp=reject

Gradual DMARC Implementation Strategy

Implementing DMARC gradually is the safest approach:

# Stage 1: Monitoring (2-4 weeks)
_dmarc IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1"

# Stage 2: Quarantine (2-4 weeks)
_dmarc IN TXT "v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@example.com"

# Stage 3: Increase quarantine
_dmarc IN TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc@example.com"

# Stage 4: Full protection
_dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; ruf=mailto:dmarc-forensic@example.com"

You can use free tools like dmarcian.com, postmarkapp.com/dmarc, or easydmarc.com to analyze DMARC reports.

Verifying All Records

Check all email security records at once:

hljs bash
# SPF check
dig TXT example.com +short | grep spf

# DKIM check
dig TXT default._domainkey.example.com +short

# DMARC check
dig TXT _dmarc.example.com +short

# MX record check
dig MX example.com +short

Email Sending Test

Send a test email from the command line:

hljs bash
# Detailed test with swaks
sudo apt install swaks -y
swaks --to test@gmail.com --from info@example.com --server localhost --tls

Check the headers of the sent email:

Authentication-Results: mx.google.com;
       dkim=pass header.d=example.com;
       spf=pass (google.com: domain of info@example.com designates SERVER_IP as permitted sender);
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com

Common Errors and Solutions

ErrorCauseSolution
SPF PermErrorMore than 10 DNS lookupsReduce include count, consolidate IP blocks
DKIM failKey mismatchPublic key in DNS must match private key on server
DMARC failSPF and DKIM alignment errorFrom header domain must match SPF/DKIM domain
SoftfailUsing ~all in SPF recordReplace with -all
Body hash mismatchEmail modified in transitSet canonicalization to relaxed/relaxed

Conclusion

The SPF, DKIM, and DMARC trio forms the foundation of email security. Properly configuring these three protocols improves email deliverability, prevents domain spoofing, and protects your brand reputation. Implement DMARC gradually, analyze reports, and ensure all legitimate sending sources are compatible with SPF and DKIM before moving to full protection.