You’ve set up your mail server, configured Postfix and Dovecot, but your emails keep landing in spam — or bouncing entirely. This guide covers the most common causes and how to diagnose each one systematically.
Diagnosing the Problem
Start with two quick tests:
Test 1: Send to mail-tester.com
Go to mail-tester.com, send an email to the address they show you, then click “Then check your score.” You get a 1–10 score with detailed explanations.
Test 2: Check your IP reputation
# Replace with your server's IP
IP="203.0.113.10"
# Check Spamhaus ZEN (covers multiple blacklists)
host -t A $(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}').zen.spamhaus.org
# Check Barracuda
host -t A $(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}').b.barracudacentral.org
If these return an IP address (like 127.0.0.2), you’re blacklisted. See the blacklist section below.
Issue 1: No SPF Record (Most Common)
Symptom: Emails fail authentication checks; received as spam or rejected.
Diagnose:
dig TXT example.com +short
If no v=spf1 record exists, that’s your problem.
Fix:
example.com. IN TXT "v=spf1 ip4:YOUR_SERVER_IP ~all"
SPF also fails if it’s misconfigured — too many DNS lookups (max 10 allowed), wrong IP, or overly permissive +all.
Issue 2: DKIM Not Signing or Failing Verification
Symptom: DKIM=fail in email headers; low mail-tester score.
Check headers — look at the raw email headers in Gmail (More → Show original):
Authentication-Results: mx.google.com;
dkim=fail (test mode) header.d=example.com
Check the DNS record exists:
dig TXT mail._domainkey.example.com +short
Check OpenDKIM is running and connected to Postfix:
sudo systemctl status opendkim
sudo grep milter /var/log/mail.log | tail -20
Common DKIM fixes:
- Key file permissions:
sudo chown opendkim:opendkim /etc/opendkim/keys/example.com/mail.private - Socket mismatch: ensure
smtpd_milters = inet:localhost:8891matchesSocket inet:8891@localhostin opendkim.conf - Wrong selector: the DNS record name must be
{selector}._domainkey.{domain}
Issue 3: No Reverse DNS (PTR Record)
Symptom: Emails rejected by major providers with messages like 550 5.7.1 ... does not have a PTR record.
Diagnose:
dig -x YOUR_SERVER_IP +short
Should return your mail hostname (e.g., mail.example.com.). If it returns nothing, the PTR is missing.
Fix: Configure the PTR record through your VPS provider’s control panel. Log in to your Vultr/DigitalOcean/etc. account and find “Reverse DNS” or “PTR” settings for your IP. Set it to mail.example.com.
Allow up to 24 hours for propagation.
Issue 4: IP Blacklisted
Symptom: Bounces with error codes like 550 IP blacklisted, or emails silently landing in spam.
Check all major blacklists at once:
Why are IPs blacklisted?
- The IP was used for spam by a previous tenant on the VPS
- Your server sent too many emails too quickly (ramp up slowly)
- You have a compromised account sending spam
Request delisting:
- Spamhaus: https://www.spamhaus.org/lookup/
- Barracuda: https://www.barracudacentral.org/rbl/removal-request
- Microsoft SNDS: https://sendersupport.olc.protection.outlook.com/snds/
If the IP is repeatedly blacklisted, you may need to request a new IP from your VPS provider or use a dedicated sending IP.
Issue 5: Missing or Wrong DMARC Record
Symptom: Gmail shows “This message did not pass security checks.”
Diagnose:
dig TXT _dmarc.example.com +short
If missing, add:
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:admin@example.com"
Read the aggregate reports (sent to the rua address) to understand what’s failing.
Issue 6: Port 25 Blocked
Symptom: Cannot send email to external servers; connections time out on port 25.
Test:
telnet smtp.gmail.com 25
# Or:
nc -zv smtp.gmail.com 25
If this times out, your VPS provider blocks outbound port 25 (common policy to prevent spam).
Fix: Contact your VPS provider’s support and request that port 25 be unblocked. Most providers require identity verification or a support ticket. Alternatively, use a transactional email relay service (Amazon SES, Mailgun, SendGrid) on port 587 for outbound mail.
Issue 7: High Spam Score from Content
Even with perfect authentication, email content can trigger spam filters.
Common content triggers:
- Excessive use of spam words (“FREE”, “CLICK NOW”, “GUARANTEED”)
- Images without text, or a very low text-to-image ratio
- Links to domains with bad reputation
- Broken HTML
- Missing unsubscribe link (for bulk mail)
Check with SpamAssassin locally:
sudo apt install spamassassin -y
echo "Test message" | spamassassin -t
Or use mail-tester.com which gives a detailed content analysis.
Issue 8: Bounce Analysis
Bounces come in two types:
Hard bounces (5xx) — permanent failures:
550 5.1.1— recipient doesn’t exist550 5.7.1— blocked by policy (your IP is blacklisted, or failing auth)550 5.4.1— no such domain
Soft bounces (4xx) — temporary failures, Postfix will retry:
421 4.7.0— rate limited, try again later452 4.2.2— recipient mailbox full
Read your mail log for bounce details:
sudo grep "status=bounced" /var/log/mail.log | tail -30
For 5.7.1 errors specifically, check authentication, IP reputation, and whether the destination domain has a strict DMARC policy.
Quick Diagnostic Checklist
Run through this list when emails aren’t delivering:
- SPF record exists and includes your server IP
- DKIM record exists and
opendkimis running - DMARC record exists
- PTR/reverse DNS set to your mail hostname
- IP not blacklisted (check MXToolbox)
- Port 25 not blocked by VPS provider
- TLS certificate valid (
sudo certbot certificates) - Postfix/Dovecot services running (
systemctl status postfix dovecot) - No errors in
/var/log/mail.log
Tools Reference
| Tool | Use |
|---|---|
| mail-tester.com | Full deliverability score |
| MXToolbox Email Health | DNS + blacklist check |
dig TXT example.com | SPF lookup |
dig TXT mail._domainkey.example.com | DKIM lookup |
dig TXT _dmarc.example.com | DMARC lookup |
dig -x IP | PTR record check |
sudo grep reject /var/log/mail.log | Rejection reasons |