First move: scan the log for severity markers¶
grep -E '(warning|error|fatal|panic):' /var/log/maillog | less # or /var/log/mail.log
journalctl -u postfix --since "1 hour ago" | grep -E '(warning|error|fatal|panic):'
The most important message is usually the earliest relevant one, not the last. Later errors are often consequences of an earlier root cause. Postfix's severity levels mean specific things:
| Level | Meaning |
|---|---|
panic |
A bug in Postfix itself. Only a code fix resolves it. Report it with the log context |
fatal |
Missing files, wrong permissions, or an invalid setting. You can fix it, but that process can't continue until you do |
error |
An error condition. A process that hits too many in a row terminates itself to avoid a runaway loop |
warning |
Non-fatal. Sometimes a real local misconfiguration (stale maps, deprecated parameters), sometimes noise from outside (broken remote DNS, quirky peers). Use judgment |
Then check the basics before going deeper:
postfix check # config syntax, file ownership and permissions
postconf -n # what's actually configured (typos show up here as warnings)
postconf 2>&1 >/dev/null # any "unused parameter" or deprecation warnings
systemctl status postfix
Common errors and what they mean¶
fatal: open database /etc/aliases.db: No such file or directory
The compiled aliases database doesn't exist (or alias_maps points somewhere unexpected). Build it:
newaliases # or: postalias /etc/aliases
systemctl restart postfix
On FreeBSD the aliases file lives at /etc/mail/aliases and Postfix's at /usr/local/etc/postfix/. Check postconf alias_maps for the real path. If the service doesn't start at all on a BSD system, also confirm postfix_enable="YES" in /etc/rc.conf.
warning: …/local: bad command startup -- throttling
This usually appears alongside the missing aliases database above. Fixing that clears this too. Otherwise, check the full log for the underlying fatal: from the local process.
warning: database /etc/postfix/xyz.db is older than source file /etc/postfix/xyz
You edited a map's source but didn't recompile it. It's the same fix for every map:
postmap /etc/postfix/xyz # postalias for /etc/aliases
postfix reload
fatal: open database /etc/postfix/xyz.db: No such file or directory
A map is referenced in main.cf but was never compiled, or the source file doesn't exist. Create it (even empty) and run postmap.
unsupported dictionary type: hash
Your Postfix build has no Berkeley DB support (increasingly common on newer distributions). Switch the map to lmdb: or cdb: and recompile. postconf -m lists the supported types (see Overview and Architecture).
warning: TLS library problem: … SSL_CTX_use_PrivateKey_file … / key values mismatch
A stale or wrong key path, commonly left behind after a certificate was renamed or renewed, or a key that doesn't match the certificate. See TLS Encryption.
warning: TLS library problem … enabling PIX workarounds
Not your bug. The peer is behind a Cisco PIX/ASA with SMTP fixup enabled, and Postfix is compensating. It's informational.
warning: request to update table btree:/var/run/smtpd_tls_session_cache in non-postfix directory /var/run
The TLS session cache must live under Postfix's data_directory:
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
Recipient address rejected: User unknown in local recipient table / … in virtual mailbox table
The address doesn't exist in any map Postfix consults for that domain. Either it really doesn't exist (the rejection is doing its job, since a typo should bounce, not vanish), or a map is missing an entry. Check which address class the domain is in and query that map:
postmap -q [email protected] hash:/etc/postfix/virtual
postmap -q [email protected] proxy:mysql:/etc/postfix/sql/virtual_mailboxes.cf
Relay access denied (554 5.7.1)
The client isn't in mynetworks, didn't authenticate, and the recipient isn't a domain you accept. For your own users, they need to submit on 587/465 with authentication rather than port 25. If the client should be trusted, add it to mynetworks carefully.
SASL authentication failed (on your server) / SASL authentication failed; server … said: 535 (relaying out)
Inbound: check Dovecot's auth log (journalctl -u dovecot), and that smtpd_sasl_path points at the socket Dovecot actually created. Outbound to a smart host: wrong credentials, a sasl_passwd key that doesn't match relayhost exactly (brackets and port included), a forgotten postmap, or a provider requiring an app password or token. On RHEL-family systems, missing cyrus-sasl-plain gives no mechanism available.
warning: pipe flag 'D' requires dovecot_destination_recipient_limit = 1
You're delivering through Dovecot's LDA via a pipe service. Add the limit, or better, switch to LMTP (see Virtual Domains and Mailboxes):
dovecot_destination_recipient_limit = 1
connect to …[…]:25: Connection timed out (outbound)
Your ISP or cloud provider blocks outbound port 25, which is very common. Test with nc -vz gmail-smtp-in.l.google.com 25. The fix is a smart host on 587/465 (see Relaying Outbound Mail), or asking the provider to unblock it.
Host or domain name not found. Name service error for name=… type=AAAA: Host not found
AAAA lookups are failing or timing out on a host with flaky or absent IPv6. Stop Postfix using IPv6 if the host doesn't have it:
inet_protocols = ipv4
Or let Postfix fall back to /etc/hosts and NSS as well as DNS:
smtp_host_lookup = dns, native
send-mail: fatal: parameter inet_interfaces: no local interface found for ::1
inet_protocols includes IPv6, but the host has IPv6 disabled. Set inet_protocols = ipv4.
status=bounced (… said: 550 5.7.1 … SPF/DKIM/DMARC …) or 5.7.26
The receiver rejected your mail on authentication. Check your SPF include for the relay, DKIM signing, and DMARC alignment (see Email Authentication and Anti-Spam).
Multi-host LAN relay problems¶
These two errors are diagnosed on the receiving host, even though you first see them in the sending host's deferred queue:
relay=none, … status=deferred (connect to host[ip]:25: No route to host)
A firewall on the destination is rejecting inbound TCP/25. (Linux firewalls often answer with ICMP host prohibited, which appears as "No route to host".) Open it on the destination:
sudo firewall-cmd --permanent --add-service=smtp && sudo firewall-cmd --reload # firewalld
sudo ufw allow from 192.0.2.0/24 to any port 25 proto tcp # ufw, LAN only
sudo nft add rule inet filter input tcp dport 25 ip saddr 192.0.2.0/24 accept # nftables
relay=none, … status=deferred (connect to host[ip]:25: Connection refused)
The host is reachable, but nothing is listening on that address. This is almost always inet_interfaces = localhost (or loopback-only) on the destination:
inet_interfaces = all
inet_interfaces changes need a full systemctl restart postfix, not just a reload. Confirm with ss -tlnp | grep ':25 '. Also make sure the destination accepts mail for that domain, or trusts the sender in mynetworks if it should relay. A working delivery looks like this:
postfix/smtp[...]: ABC123: to=<[email protected]>, relay=desktop.lan.example[192.0.2.20]:25, delay=0.3, status=sent (250 2.0.0 Ok: queued as DEF456)
postfix/qmgr[...]: ABC123: removed
Verbose logging for one peer¶
When the normal log isn't enough, turn on verbose logging for just the problem host instead of the whole server:
debug_peer_list = 203.0.113.5 # or a hostname or domain
debug_peer_level = 2
postfix reload, reproduce the problem, then remove it again. The output is very large and can include message content. For TLS-specific detail, temporarily raise smtp_tls_loglevel or smtpd_tls_loglevel to 2.
General debugging workflow¶
- Find the earliest relevant error:
grep -E '(warning|error|fatal|panic):', then follow the queue ID through the log. - Validate the config:
postfix check,postconf -n, and any deprecation warnings. - Reproduce by hand: a manual SMTP session (
telnet/nc,openssl s_client -starttls smtp, orswaks) separates "Postfix's accept/queue logic" from "the route or recipient that's failing". - Check the maps: did you re-run
postmap/postaliasafter the last edit?postmap -qthe exact key. This is the single most common mistake. - Check the outside world: DNS (
dig MX,dig -x), reachability (nc -vz host 25), blocklists for your IP, and the peer's response text inpostqueue -p. - TLS problems: see TLS Encryption's troubleshooting section and
posttls-finger. - Two hosts you control: check both ends' logs. "No route to host" and "Connection refused" are fixed on the receiving end.