The Three SMTP Errors Every Admin Hits
If you manage a mail server long enough, you'll see all three: Connection Refused, Connection Timed Out, and Relay Access Denied. They look similar but have completely different root causes. This guide walks through each one with the CLI commands that tell you exactly what's broken.
Error 1: Connection Refused
A connection refused error means the remote server actively rejected your TCP connection. Either nothing is listening on port 25/587/465, a firewall is blocking it, or the MTA process itself is down.
Diagnosis
# Quick test — is the port actually open?
nc -zv mail.example.com 25
# Connection refused output:
# nc: connect to mail.example.com (192.0.2.1) port 25 (tcp) failed: Connection refused
# Check what's listening locally (on the mail server itself)
ss -tlnp | grep -E ':25|:587|:465'
# Expected output (Postfix running):
# LISTEN 0 100 0.0.0.0:25 0.0.0.0:* users:(("master",pid=1234,fd=13))
# Nothing? MTA is down. Check service status:
systemctl status postfix
# or
systemctl status exim4
Common Causes and Fixes
- MTA not running:
systemctl start postfixandsystemctl enable postfix. Check/var/log/mail.logfor why it died — usually a syntax error inmain.cfor/etc/exim4/conf.d/. - Binding to localhost only: Check
inet_interfacesin Postfix'smain.cf. If it's set tolocalhostor127.0.0.1, change it toalland restart. - Firewall blocking port 25: Many VPS providers block outbound port 25 by default to combat spam. Check with
iptables -L -n | grep :25and also verify with your hosting provider — AWS, DigitalOcean, and Linode all require you to request port 25 unblocking. - ISP-level block: Some ISPs block outbound 25 from residential IPs. Test from a different network or use OpsCheck SMTP Tester to probe your server from an external network.
Use the OpsCheck Port Scanner to verify that ports 25, 587, and 465 are reachable from the internet. The tool scans all common mail ports and reports which ones respond — faster than asking a colleague on a different network to test for you.
Error 2: Connection Timed Out
A timeout means the TCP SYN packet never received a SYN-ACK back. Unlike "connection refused" (which is an active rejection), a timeout is passive — the packet is being dropped somewhere in the network path.
Diagnosis
# Timeout from nc:
nc -zv -w 10 mail.example.com 25
# nc: connect to mail.example.com port 25 (tcp) timed out
# Trace the path to see where packets die
traceroute -T -p 25 mail.example.com
# or with MTR for continuous probing
mtr -T -P 25 mail.example.com
# Check if ANY port is reachable (rule out total server unreachability)
nc -zv -w 5 mail.example.com 22
# If SSH works but SMTP doesn't, you have a port-specific block
Common Causes
- Hosting provider outbound filter: The most common cause. Providers silently drop outbound port 25 SYN packets. Check your provider's documentation. Use the SMTP Tester from an external location to confirm the port is open from outside.
- Stateful firewall dropping return traffic: If you recently added
iptablesrules, verify you have an ESTABLISHED/RELATED rule that allows return packets. - Wrong IP or hostname: DNS resolves to a stale IP after a migration. Always verify:
dig +short A mail.example.comand compare to the actual server IP. - Server firewall with default DROP policy:
iptables -L INPUT -nshould show an explicit ACCEPT for port 25. A DROP policy without an ACCEPT rule for SMTP ports causes timeouts, not refusals.
The Port Scanner confirms reachability from an external vantage point. The SMTP Tester goes further — it performs a full SMTP handshake and tells you whether the server responds with a valid banner.
Error 3: Relay Access Denied (554 5.7.1)
This is an SMTP-level rejection, not a network problem. The server is reachable and accepting connections, but it refuses to relay your message. The error appears after RCPT TO: in the SMTP conversation.
# Reproduce the full SMTP conversation manually
telnet mail.example.com 25
# or with STARTTLS on port 587:
openssl s_client -starttls smtp -connect mail.example.com:587 -crlf
SMTP Conversation Walkthrough
220 mail.example.com ESMTP Postfix
EHLO mylaptop.local
250-mail.example.com
250-PIPELINING
250-SIZE 10240000
250-STARTTLS
250-AUTH PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250 CHUNKING
MAIL FROM:<sender@example.com>
250 2.1.0 Ok
RCPT TO:<recipient@otherdomain.com>
554 5.7.1 <recipient@otherdomain.com>: Relay access denied
The key line is the 554 after RCPT TO. Postfix and Exim both reject relaying when the recipient domain doesn't match the server's configured domains and the sender hasn't authenticated.
Root Causes and Fixes
Cause A: Not Authenticated
If you're connecting from outside the server's network, you must authenticate with SMTP AUTH before sending. Check if AUTH is advertised (look for 250-AUTH PLAIN LOGIN in the EHLO response). If it's missing, enable it in your MTA config.
# Postfix: check /etc/postfix/main.cf
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
Cause B: mynetworks Not Configured
Postfix allows relay from IPs in mynetworks without authentication. If your application server's IP isn't listed, relay is denied.
# Postfix main.cf
mynetworks = 127.0.0.0/8, 10.0.0.0/8, 192.168.1.0/24
# After changing, reload:
postconf -e "mynetworks = 127.0.0.0/8, 10.0.0.0/8, YOUR_APP_SERVER_IP/32"
systemctl reload postfix
Cause C: $mydestination Missing the Domain
If the server should accept mail for a domain (not relay through it), the domain must be in mydestination for Postfix or dc_other_hostnames for Exim.
# Postfix: domains this server accepts mail for (final delivery)
postconf mydestination
# Add your domain if missing:
postconf -e "mydestination = \$myhostname, localhost.\$mydomain, localhost, example.com, otherdomain.com"
systemctl reload postfix
Cause D: Connecting on Port 25 Without Authentication
Port 25 is for server-to-server mail delivery (MX-to-MX). Client submissions should use port 587 (STARTTLS) or 465 (TLS wrapper) with authentication. Connecting on port 25 and trying to relay without being in mynetworks will always be denied.
Real-World Scenario: Migration Gone Wrong
A team migrated their web app from one VPS to another. The app used the old server's Postfix for outbound mail. After migration, all emails failed with "relay access denied."
The original setup had the app server's old IP in Postfix's mynetworks. The new server's IP wasn't added. The dev team spent two hours debugging application code before checking the MTA config.
# The fix took 30 seconds:
postconf -e "mynetworks = 127.0.0.0/8, NEW_SERVER_IP/32"
systemctl reload postfix
# Verified with:
echo "Test" | mail -s "Test" -r app@example.com admin@example.com
tail -f /var/log/mail.log
Moral: when you change IP addresses, update every mynetworks entry, every firewall rule, and every SPF record. Use the SMTP Tester after every migration to confirm the handshake succeeds before your users notice.
Systematic Troubleshooting Flow
When mail delivery breaks, follow this order. Don't jump to step 4 before ruling out step 1.
- Can you reach the port? —
nc -zv mail.example.com 25or use the Port Scanner. If connection refused, the MTA is down or firewalled. If timeout, there's a network-level block. - Does the SMTP handshake succeed? — Use the SMTP Tester for a full handshake. Check the banner, EHLO capabilities, and whether STARTTLS is offered.
- Are you authenticated or authorized? — If relay denied, either authenticate with SMTP AUTH or add your IP to
mynetworks. - Is the mail being accepted but then disappearing? — Check
/var/log/mail.logfor delivery status. The MTA accepted it — now check SPF/DKIM/DMARC (use the Email Authentication tool) and blacklist status.
The SMTP Tester and Port Scanner together answer steps 1 and 2 in under 10 seconds. Start there — most mail problems are network-layer, not application-layer.