← Back to posts
comparison guide self-hosted · · 13 min read

Complete Guide to Self-Hosted Email Deliverability & Inbox Placement 2026

Comprehensive guide to self-hosted email deliverability — SPF, DKIM, DMARC, MTA-STS, BIMI, IP reputation monitoring, inbox placement testing, and bounce handling. Tools, configs, and strategies for keeping your self-hosted email out of spam folders.

OS
Editorial Team

Setting up a self-hosted mail server is only half the battle. The real challenge is ensuring your emails actually land in the recipient’s inbox instead of the spam folder. Google, Yahoo, Microsoft, and other major providers use hundreds of signals to evaluate incoming mail — and without proper authentication, reputation monitoring, and deliverability testing, even legitimate messages from your own domain will be rejected.

This guide covers the complete stack of self-hosted email deliverability tools and strategies for 2026: DNS authentication records, transport security protocols, reputation monitoring, inbox placement testing, and bounce management. For background on setting up the mail server itself, see our complete Postfix + Dovecot + Rspamd mail server guide and DMARC analysis tools comparison.

Why Email Deliverability Matters for Self-Hosted Servers

When you send email from a cloud provider like SendGrid or Mailgun, deliverability is mostly handled for you. They maintain IP reputation pools, manage feedback loops, and negotiate whitelists with major providers. When you self-host, you own the entire chain — and any weak link breaks delivery.

The most common reasons self-hosted email ends up in spam:

ProblemImpactSelf-Hosted Fix
Missing SPF recordHigh — major spam signalAdd DNS TXT record
Missing DKIM signatureHigh — no cryptographic proofConfigure OpenDKIM/Rspamd
No DMARC policyMedium — no enforcement guidancePublish DMARC DNS record
No reverse DNS (PTR)High — looks like spam infrastructureConfigure with hosting provider
Poor IP reputationCritical — immediate spam filteringWarm-up IP, monitor blacklists
No MTA-STSLow — missed TLS enforcementPublish MTA-STS policy
No TLS-RPTLow — can’t detect TLS failuresSet up TLS reporting
No BIMINone — visual brand indicator onlyPublish BIMI DNS record
Sending too fast initiallyHigh — triggers rate limitsGradual IP warm-up
High bounce rateCritical — IP gets blacklistedBounce handling + list hygiene

For protecting your domain from spoofing attempts, our DMARC analysis guide covers parsedmarc and OpenDMARC in detail. This article focuses on the broader deliverability stack.

DNS Authentication: The Foundation of Email Deliverability

Every email deliverability strategy starts with three DNS records that prove you’re the legitimate sender.

SPF (Sender Policy Framework)

SPF tells receiving servers which IP addresses are authorized to send email on behalf of your domain. A properly configured SPF record looks like this:

1
example.com.  IN  TXT  "v=spf1 mx ip4:203.0.113.50 ip6:2001:db8::1 include:_spf.example.com -all"
MechanismMeaning
mxAllow your domain’s MX servers to send
ip4:x.x.x.xAllow specific IPv4 address
ip6:xxxxAllow specific IPv6 address
include:domain.comInclude another domain’s SPF policy
-allHard fail — reject all others
~allSoft fail — mark as suspicious but accept

Best practice: Use -all (hard fail) only after you’ve confirmed all your sending sources are listed. Start with ~all during setup.

DKIM (DomainKeys Identified Mail)

DKIM adds a cryptographic signature to each outgoing email. The receiving server verifies the signature against a public key published in your DNS:

1
mail._domainkey.example.com.  IN  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."

With Rspamd (recommended over standalone OpenDKIM for most setups), DKIM signing is configured in /etc/rspamd/local.d/dkim_signing.conf:

1
2
3
4
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "mail";
allow_username_mismatch = true;
sign_networks = "/etc/rspamd/local.d/signed_networks.inc";

Generate a 2048-bit key:

1
2
3
rspamadm dkim_keygen -s mail -d example.com -k /var/lib/rspamd/dkim/example.com.mail.key > /var/lib/rspamd/dkim/example.com.mail.pub
cat /var/lib/rspamd/dkim/example.com.mail.pub
# Paste the public key into DNS as shown above

DMARC (Domain-based Message Authentication, Reporting & Conformance)

DMARC ties SPF and DKIM together and tells receivers what to do when authentication fails:

1
_dmarc.example.com.  IN  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; pct=100; adkim=s; aspf=s"
TagValuePurpose
pnone, quarantine, rejectPolicy for failed authentication
ruamailto:reports@...Where to send aggregate reports
rufmailto:forensic@...Where to send forensic reports
pct0100Percentage of mail to apply policy to
adkimr (relaxed), s (strict)DKIM alignment mode
aspfr (relaxed), s (strict)SPF alignment mode

Recommended rollout: Start with p=none for 2–4 weeks while monitoring reports, move to p=quarantine, then p=reject once you’re confident all legitimate sources are authenticated.

Transport Security: MTA-STS and TLS-RPT

Beyond authentication, modern email deliverability requires encrypted transport between mail servers.

MTA-STS (SMTP MTA Strict Transport Security)

MTA-STS (RFC 8461) is like HTTP Strict Transport Security (HSTS) but for email. It tells sending servers to only deliver mail to your MX servers over TLS connections with valid certificates.

Two DNS records are required:

1
2
3
4
# 1. MTA-STS policy discovery
_mta-sts.example.com.  IN  TXT  "v=STSv1; id=2026042401;"

# 2. Policy file hosted at https://mta-sts.example.com/.well-known/mta-sts.txt

The policy file (served via HTTPS):

1
2
3
4
5
version: STSv1
mode: enforce
mx: mail.example.com
mx: mail2.example.com
max_age: 86400
ModeBehavior
noneTesting only — do not enforce
testingLog failures but do not reject
enforceReject mail if TLS cannot be established

Self-hosted MTA-STS implementation with Nginx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
server {
    listen 443 ssl;
    server_name mta-sts.example.com;

    ssl_certificate /etc/letsencrypt/live/mta-sts.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mta-sts.example.com/privkey.pem;

    location /.well-known/mta-sts.txt {
        add_header Content-Type text/plain;
        alias /etc/nginx/mta-sts.txt;
    }
}

TLS-RPT (TLS Reporting)

TLS-RPT sends you reports when other servers fail to establish TLS connections with your mail servers. This is invaluable for catching certificate expiry issues and misconfigurations.

1
_smtp._tls.example.com.  IN  TXT  "v=TLSRPTv1; rua=mailto:tls-reports@example.com"

Reports arrive as JSON files via email, similar to DMARC aggregate reports. You can parse them with the same tools used for DMARC.

BIMI: Brand Indicators for Message Identification

BIMI displays your logo next to authenticated emails in supporting inboxes (Gmail, Yahoo, Apple Mail). While it doesn’t directly improve deliverability, it increases brand trust and can improve engagement rates.

1
default._bimi.example.com.  IN  TXT  "v=BIMI1; l=https://example.com/bimi/logo.svg; a=https://example.com/bimi/cert.pem"

Requirements:

  • SVG logo in Square format (1:1 ratio, min 32x32px)
  • DMARC policy set to p=quarantine or p=reject
  • Verified Mark Certificate (VMC) from a certified authority (paid)

Self-Hosted Deliverability Tools Comparison

Once your DNS records are configured, you need tools to monitor and test your deliverability. Here are the best self-hosted options:

ToolStarsLanguagePrimary UseDockerActive
parsedmarc1,232PythonDMARC/TLS-RPT report parsing & visualizationYes2026-04
happydeliver207GoInbox placement testing, deliverability scoringYes2026-04
Haraka5,562JavaScriptPlugin-based SMTP server with deliverability pluginsYes2026-04
PostfixDashboardPythonReal-time Postfix monitoring and analyticsYes2025-11
mailwatcher2GoEmail domain and IP reputation monitoringYes2024-12
espoofer1,694PythonEmail spoofing and SPF/DKIM/DMARC testingYes2022-05

parsedmarc: DMARC and TLS-RPT Report Analysis

parsedmarc is the most popular self-hosted DMARC report parser. It ingests aggregate reports via IMAP, parses the XML, stores results in Elasticsearch, and visualizes them in Kibana or Grafana.

Docker Compose deployment:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
services:
  parsedmarc:
    image: domainaware/parsedmarc:latest
    container_name: parsedmarc
    restart: unless-stopped
    volumes:
      - ./parsedmarc.ini:/etc/parsedmarc.ini:ro
    depends_on:
      - elasticsearch

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    volumes:
      - es_data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    container_name: kibana
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

volumes:
  es_data:

Configuration file (parsedmarc.ini):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
[general]
save_daily_aggregate = true

[imap]
host = imap.example.com
port = 993
ssl = true
user = dmarc-reports@example.com
password = your-password
watch = true

[elasticsearch]
hosts = ["http://elasticsearch:9200"]

[smtp]
host = localhost
port = 25
ssl = false
user = ""
password = ""
from = dmarc-reports@example.com
to = admin@example.com

happydeliver: Self-Hosted Inbox Placement Testing

happydeliver by happyDomain is an open-source deliverability testing platform. It sends test emails to various providers and checks whether they land in the inbox, spam folder, or get rejected entirely.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
services:
  happydeliver:
    image: ghcr.io/happydomain/happydeliver:latest
    container_name: happydeliver
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - SMTP_HOST=mail.example.com
      - SMTP_PORT=587
      - SMTP_USER=test@example.com
      - SMTP_PASSWORD=your-password
      - DATABASE_URL=sqlite:///data/happydeliver.db
    volumes:
      - ./happydeliver_data:/data

Key features:

  • Tests inbox placement across major providers (Gmail, Yahoo, Outlook, etc.)
  • Analyzes email headers for authentication results
  • Tracks SPF, DKIM, and DMARC pass/fail status
  • Monitors spam score from common filters
  • Historical trend tracking for deliverability scores

Haraka: Plugin-Based SMTP Server with Deliverability Plugins

Haraka is a highly extensible Node.js SMTP server with a rich plugin ecosystem specifically designed for outbound email deliverability.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
services:
  haraka:
    image: haraka/haraka:latest
    container_name: haraka
    restart: unless-stopped
    ports:
      - "25:25"
      - "587:587"
    volumes:
      - ./haraka/config:/haraka/config
      - ./haraka/plugins:/haraka/plugins
    environment:
      - HARAKA_HOST_LIST=example.com
      - HARAKA_ME=mail.example.com

Key deliverability plugins:

PluginPurpose
dkim_signSigns outgoing messages with DKIM
spfValidates SPF for incoming mail
block_meBlock mail to specific recipients
record_envelope_addressesLogs envelope data for analytics
log.syslogStructured logging for monitoring
dnsblCheck sender IPs against DNS blocklists
helo.checksValidate HELO/EHLO hostname
rate_limitThrottle outbound sending rate

Install and configure the DKIM signing plugin:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Inside Haraka config directory
echo "dkim_sign" >> config/plugins

cat > config/dkim_sign.ini << 'EOF'
domain = example.com
selector = mail
headers_from_dn = true
headers_from_separator = +
key_dir = /haraka/config/dkim
EOF

# Generate DKIM key
openssl genrsa -out config/dkim/mail.private 2048
openssl rsa -in config/dkim/mail.private -pubout -out config/dkim/mail.public

Postfix Monitoring with Prometheus

For real-time Postfix monitoring, the smtp_exporter exposes queue metrics, delivery rates, and bounce counts to Prometheus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
services:
  postfix_exporter:
    image: kumquat/postfix-exporter:latest
    container_name: postfix_exporter
    restart: unless-stopped
    ports:
      - "9154:9154"
    volumes:
      - /var/log/mail.log:/var/log/mail.log:ro
    command:
      - "--postfix.showq_path=/var/spool/postfix/public/showq"
      - "--log.path=/var/log/mail.log"

Prometheus scrape configuration:

1
2
3
4
scrape_configs:
  - job_name: postfix
    static_configs:
      - targets: ["postfix_exporter:9154"]

IP Reputation Monitoring and Blacklist Checking

Your server’s IP reputation is the single most important factor in inbox placement. Here’s how to monitor it:

Checking Blacklists

Use these free DNSBL (DNS-based Blocklist) services to check your IP:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Check if your IP is listed on common blacklists
IP="203.0.113.50"
REVERSED=$(echo "$IP" | awk -F. '{print $4"."$3"."$2"."$1}')

for bl in zen.spamhaus.org bl.spamcop.net b.barracudacentral.org dnsbl.sorbs.net; do
  RESULT=$(dig +short ${REVERSED}.${bl} A 2>/dev/null)
  if [ -n "$RESULT" ]; then
    echo "❌ Listed on $bl: $RESULT"
  else
    echo "✅ Clean on $bl"
  fi
done

Automated Reputation Monitoring

Deploy a self-hosted reputation checker that runs daily:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash
# /etc/cron.daily/email-reputation-check.sh

MY_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
REVERSED=$(echo "$MY_IP" | awk -F. '{print $4"."$3"."$2"."$1}')
ALERT_EMAIL="admin@example.com"

BLACKLISTS=(
  "zen.spamhaus.org"
  "bl.spamcop.net"
  "b.barracudacentral.org"
  "dnsbl.sorbs.net"
  "cbl.abuseat.org"
  "bl.mailspool.net"
  "dnsbl-1.uceprotect.net"
  "pbl.spamhaus.org"
)

LISTED=0
for bl in "${BLACKLISTS[@]}"; do
  RESULT=$(dig +short ${REVERSED}.${bl} A 2>/dev/null)
  if [ -n "$RESULT" ]; then
    LISTED=1
    echo "ALERT: IP $MY_IP listed on $bl ($RESULT)"
  fi
done

if [ "$LISTED" -eq 1 ]; then
  echo "Email server IP $MY_IP is listed on one or more blacklists." | \
    mail -s "URGENT: IP Blacklist Alert" "$ALERT_EMAIL"
fi

Email Warm-Up Strategy for New IPs

When starting with a new IP address, you must gradually increase your sending volume to build a positive reputation with major providers.

Week-by-Week Warm-Up Schedule

WeekDaily VolumePurpose
150–100 emailsEstablish baseline, target engaged users
2200–500 emailsIncrease gradually, monitor bounce rate
3500–1,000 emailsExpand to broader segments
41,000–2,000 emailsNormal volume with continued monitoring
5+Scale as neededMaintain consistent sending patterns

Postfix rate limiting configuration for warm-up:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# /etc/postfix/main.cf
# Limit outbound connections per destination
default_destination_rate_delay = 1s
default_destination_concurrency_limit = 5
default_destination_recipient_limit = 10

# Slow down during warm-up period
smtp_destination_rate_delay = 5s
smtp_destination_concurrency_limit = 3
smtp_destination_recipient_limit = 5

Bounce Handling and List Hygiene

High bounce rates (>2%) are the fastest way to get your IP blacklisted. Self-hosted bounce handling requires:

  1. Processing bounce notifications — parse Delivery Status Notifications (DSNs)
  2. Categorizing bounces — hard bounce (permanent) vs. soft bounce (temporary)
  3. Suppressing hard bounces — remove permanently failed addresses immediately
  4. Managing soft bounces — retry up to 3–5 times over 24–48 hours before suppressing

If you run marketing campaigns, integrate bounce handling with Listmonk or Mautic for automatic list cleaning.

Deliverability Testing Checklist

Before sending production email, verify every item:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. Check SPF record
dig +short TXT example.com | grep "v=spf1"

# 2. Check DKIM record
dig +short TXT mail._domainkey.example.com | grep "v=DKIM1"

# 3. Check DMARC record
dig +short TXT _dmarc.example.com | grep "v=DMARC1"

# 4. Check reverse DNS (PTR)
dig -x 203.0.113.50 +short

# 5. Check MTA-STS policy
curl -s https://mta-sts.example.com/.well-known/mta-sts.txt

# 6. Check TLS-RPT record
dig +short TXT _smtp._tls.example.com | grep "v=TLSRPTv1"

# 7. Check BIMI record
dig +short TXT default._bimi.example.com | grep "v=BIMI1"

# 8. Test with espoofer (spoofing test)
docker run --rm -it chenjj/espoofer -d example.com -f sender@example.com -t test@gmail.com

Email Testing Sandbox

For development and testing, use Mailpit vs MailHog vs MailCatcher to catch all outbound emails in a local sandbox. This prevents accidental delivery to real recipients while you’re configuring authentication records and testing deliverability.

Frequently Asked Questions

How long does it take for a new IP to build email reputation?

Typically 4–8 weeks of consistent, gradual sending. Major providers like Gmail and Yahoo use machine learning models that need time to establish a trust baseline. Start with 50–100 emails per day and increase by 2x each week. Sending large volumes immediately from a new IP will almost certainly trigger spam filters.

What is a good bounce rate for self-hosted email?

Keep your hard bounce rate below 2% and your total bounce rate (hard + soft) below 5%. Google and Yahoo will start rejecting mail from senders with bounce rates above these thresholds. If your bounce rate spikes, immediately pause sending and clean your mailing lists.

Do I need MTA-STS for email deliverability?

MTA-STS is not strictly required for inbox placement, but it’s becoming a strong positive signal. It demonstrates to receiving servers that you take transport security seriously. Google and Yahoo have both stated they consider MTA-STS as a factor in their filtering decisions. Combined with TLS-RPT, it gives you visibility into TLS connection failures that would otherwise go unnoticed.

Can I self-host email deliverability testing for multiple domains?

Yes. Tools like parsedmarc support monitoring multiple domains by configuring separate IMAP accounts for each domain’s DMARC/TLS-RPT report mailbox. happydeliver allows configuring multiple sending domains and testing each independently. For larger operations, consider deploying a central Elasticsearch cluster to aggregate reports from all domains into a single dashboard.

How do I know if my email is being throttled by Gmail or Yahoo?

Look for these signs in your Postfix or Haraka logs:

  • Increased delivery latency (messages taking 5+ minutes instead of seconds)
  • Temporary 4xx SMTP responses from receiving servers
  • Rate limit messages like “421 too many connections” or “450 rate limit exceeded”
  • Sudden drops in delivery success rate for a specific provider

What should I do if my IP gets blacklisted?

  1. Identify the blacklist — use the blacklist checking script above
  2. Find the reason — check the blacklist’s website for delisting instructions
  3. Fix the root cause — was it a spam complaint, open relay, or infected machine?
  4. Request delisting — most blacklists have an automated delisting form
  5. Monitor — re-check your IP status after 24 hours
  6. Prevent recurrence — implement rate limiting, bounce handling, and spam filtering

Is BIMI worth setting up for self-hosted email?

BIMI doesn’t directly improve deliverability scores, but it provides significant brand benefits. Your logo appears next to authenticated emails in Gmail, Yahoo, and Apple Mail, which increases brand recognition and trust. The main barrier is the Verified Mark Certificate (VMC), which costs $100–500/year from certified authorities. If you’re a business sending regular email to customers, the trust signal is worth the cost. For personal or low-volume use, you can skip BIMI without impacting inbox placement.

Advertise here
Advertise here