Email Security

DKIM Explained: How Email Signing Works and How to Set It Up

DKIM (DomainKeys Identified Mail) cryptographically signs your outbound email to prove it wasn't tampered with. Learn how DKIM signing works, how to add your DNS record, and how to troubleshoot failures.

October 28, 20256 min readShipSafer Team

DKIM (DomainKeys Identified Mail) is an email authentication mechanism that uses public-key cryptography to prove that an email message was sent by an authorized server and wasn't modified in transit. Without DKIM, anyone can forge the From: address in an email, and there's no way for receiving servers to detect tampering.

DKIM is one of the three pillars of email authentication (SPF, DKIM, DMARC) and is now required by Google and Yahoo for bulk senders.

How DKIM Works

  1. Your mail server holds a private key
  2. You publish the corresponding public key in a DNS TXT record
  3. When you send an email, your mail server signs specific headers and the message body using the private key, adding a DKIM-Signature header
  4. The receiving mail server looks up your public key in DNS
  5. It uses the public key to verify the signature
  6. If the signature is valid, DKIM passes — proving the message came from someone with access to your private key and wasn't modified in transit

The DKIM-Signature Header

A DKIM signature looks like this:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  d=yourdomain.com; s=google;
  h=from:to:subject:date:message-id;
  bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
  b=RZ4QL2tBqoABnVb3ZN9bPFCb7y...

Key tags:

TagMeaning
v=1DKIM version
a=rsa-sha256Signing algorithm
c=relaxed/relaxedCanonicalization (header/body)
d=yourdomain.comSigning domain
s=googleSelector (identifies which public key to use)
h=from:to:subject:...Headers that are signed
bh=...Hash of the message body
b=...The actual cryptographic signature

DKIM DNS Record Format

The public key is published at {selector}._domainkey.{domain}:

google._domainkey.yourdomain.com TXT
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
TagMeaning
v=DKIM1Record version
k=rsaKey type (rsa or ed25519)
p=...Base64-encoded public key
t=sOptional: s = signing only (no subdomain delegation)
t=yOptional: y = test mode (failures not enforced)

To revoke a DKIM key (key rotation or compromise), publish an empty p= tag:

google._domainkey.yourdomain.com TXT "v=DKIM1; p="

The Selector

The selector (s= tag) is a name you choose that identifies which key pair to use. Multiple selectors allow multiple keys — useful for:

  • Different email services (one for Google Workspace, one for SendGrid)
  • Key rotation (add a new selector before revoking the old one)

Common selector names: google, mail, selector1, s1, your service name

Setting Up DKIM

Google Workspace

  1. Admin Console → Apps → Google Workspace → Gmail → Authenticate email
  2. Click "Generate new record" for your domain
  3. Copy the DNS TXT record value
  4. Add TXT record at google._domainkey.yourdomain.com
  5. Return to Admin Console and click "Start authentication"

Microsoft 365

  1. Admin Center → Settings → Domains → select your domain
  2. DKIM tab → Enable

Or via PowerShell:

New-DkimSigningConfig -DomainName yourdomain.com -Enabled $true

SendGrid

  1. Settings → Sender Authentication → Authenticate Your Domain
  2. Choose your DNS provider
  3. SendGrid generates two CNAME records; add them to your DNS
  4. SendGrid manages key rotation automatically via CNAMEs

Amazon SES

# Request DKIM verification
aws sesv2 create-email-identity --email-identity yourdomain.com

# Get the DNS records to add
aws sesv2 get-email-identity --email-identity yourdomain.com \
  --query 'DkimAttributes.Tokens'

Add CNAME records at token._domainkey.yourdomain.com pointing to token.dkim.amazonses.com.

Postfix (Self-Hosted)

Use OpenDKIM:

# Install
sudo apt install opendkim opendkim-tools

# Generate key
sudo opendkim-genkey -t -s mail -d yourdomain.com

# Key is in /etc/opendkim/keys/
# Add the public key from mail.txt to DNS
cat /etc/opendkim/keys/mail.txt

RSA-SHA256 vs Ed25519

Traditional DKIM uses RSA-SHA256 with a 1024-bit or 2048-bit key. RFC 8463 added support for Ed25519-SHA256, which is:

  • Shorter key (32 bytes vs 256+ bytes for RSA-2048)
  • Faster to sign and verify
  • Considered more secure than RSA-1024

Most major mail servers support Ed25519, but some older mail clients don't. Best practice: publish both and sign with both when possible.

Verifying DKIM

Check the DNS record

dig TXT google._domainkey.yourdomain.com +short

You should see a TXT record starting with v=DKIM1.

Check a received email's signature

Send an email to yourself and view the raw headers. Look for the DKIM-Signature header and the Authentication-Results header from the receiving server:

Authentication-Results: mx.google.com;
  dkim=pass header.i=@yourdomain.com header.s=google header.b=RZ4QL2tB;
  spf=pass ...;
  dmarc=pass ...

dkim=pass confirms the signature verified successfully.

Using the command line

# Check if a DKIM record exists for a given selector
dig TXT google._domainkey.yourdomain.com

# Test DKIM configuration with swaks
swaks --to test@gmail.com \
  --from you@yourdomain.com \
  --server mail.yourdomain.com \
  --auth-user you@yourdomain.com \
  --auth-password yourpassword

Common DKIM Problems

dkim=fail (body hash did not verify)

The message body was modified in transit after signing. Common causes:

  • Mailing list software that appends footers (breaks body hash)
  • Content scanners that modify the message body
  • Line ending normalization

Solution: Use c=relaxed/relaxed canonicalization (which handles common whitespace changes) and work with mailing list providers.

dkim=fail (signature did not verify)

The signature itself is invalid. Causes:

  • Key was rotated without updating the DNS record
  • Wrong selector in DNS
  • Signing with a different key than what's published

dkim=permerror (no key for signature)

No DNS record found for the selector. Either:

  • DNS record not published yet (propagation delay)
  • Wrong selector name in DNS vs s= tag
  • DNS record expired or deleted

dkim=neutral (message not signed)

The message has no DKIM signature. Your sending server isn't signing outbound mail.

DKIM and Email Forwarding

Email forwarding breaks SPF (the forwarding server isn't in your SPF record) but DKIM survives forwarding because the signature is over the message content, not the sending server's IP. This is why DKIM alignment is the more reliable authentication mechanism for forwarded mail in DMARC evaluation.

Key Rotation

Rotate DKIM keys at least annually, or immediately if:

  • A private key is compromised
  • A server with access to the private key is decommissioned
  • A team member with key access leaves (for self-managed keys)

Rotation process:

  1. Generate a new key pair with a new selector name (s2 if current is s1)
  2. Publish the new public key in DNS: s2._domainkey.yourdomain.com
  3. Wait for DNS propagation (24–48 hours)
  4. Update your mail server to sign with the new key and selector
  5. Monitor for a week to ensure no issues
  6. Revoke the old key: set p= to empty in the old selector's DNS record
dkim
email-security
dns
cryptography
dmarc

Check Your Security Score — Free

See exactly how your domain scores on DMARC, TLS, HTTP headers, and 25+ other automated security checks in under 60 seconds.