You see status=deferred (connect to mx.example.com[192.0.2.1]:25: Connection refused) filling your mail logs. The deferred queue is growing. Postfix cannot establish outbound TCP connections to destination mail servers.

“Connection refused” is not the same as “Connection timed out.” Connection refused means the TCP handshake was actively rejected with a RST packet: the destination IP is reachable, but nothing is listening on that port, or something in the path is rejecting the connection. Connection timed out means the SYN packet was silently dropped: a firewall rule, a network partition, or an ISP dropping egress traffic.

A sub-second connect delay in the log’s delays= field confirms Connection refused. A connect delay near your smtp_connect_timeout (default 30 seconds) confirms Connection timed out.

What this means

When Postfix logs Connection refused, the smtp delivery agent attempted a TCP connect to the destination MX, relayhost, or transport_maps target on port 25 and received an immediate RST. Postfix classifies this as a temporary failure (DSN 4.4.1), defers the message, and schedules a retry with exponential backoff. The deferred queue grows as long as the condition persists.

The canonical log pattern:

postfix/smtp[PID]: QUEUEID: to=<user@domain>, relay=none, delay=0.8,
  delays=0.1/0.1/0.5/0.1, dsn=4.4.1, status=deferred
  (connect to mx.example.com[192.0.2.1]:25: Connection refused)

Three fields tell you what happened:

  • relay=none: Postfix never reached the destination. No SMTP session was established.
  • delays= third field (connect time): Sub-second means actively refused. Near 30 seconds means timed out. This is your primary triage signal.
  • connect to <host>[<ip>]:<port>: The specific host and port Postfix tried to reach. This tells you whether the problem is a content filter on localhost, a relayhost, a transport_maps target, or a destination MX.

Common causes

CauseWhat it looks likeFirst thing to check
Cloud or ISP egress blocking port 25All outbound deliveries to any MX refused; relay=none on every messageTest direct TCP to a well-known MX on port 25 from the server
relayhost set but not listeningEvery outbound message defers to the same relayhost address and portpostconf -h relayhost, then test that host on port 25
Content filter port downLogs show connect to 127.0.0.1[127.0.0.1]:10024: Connection refusedCheck whether amavisd, rspamd, or other filter process is running
transport_maps overriding relayhostSome domains deliver normally; others refuse despite relayhost being setpostconf -h transport_maps and inspect entries for affected domains
Destination MX not accepting connectionsOnly one destination affected; all others deliver normallydig MX domain, then test TCP to each returned MX on port 25
Postfix delivering to itselfRefused to own IP on port 25; smtpd only listening on localhostCheck mydestination, virtual_alias_domains, and inet_interfaces

Quick checks

# Confirm the error pattern and count recent refusals
grep 'Connection refused' /var/log/mail.log | tail -20

# Check connect delay timing (refused is sub-second; timed out is near 30s)
grep 'Connection refused' /var/log/mail.log | grep -oE 'delays=[^ ]+' | tail -10

# Check if relayhost is configured
postconf -h relayhost

# Check transport_maps for domain-specific overrides
postconf -h transport_maps

# Check smtp_connect_timeout (confirms timeout boundary)
postconf -h smtp_connect_timeout

# Test direct TCP to a known MX on port 25
nc -w 5 -zv gmail-smtp-in.l.google.com 25

# Check for content filter refusals to localhost
grep 'connect to 127.0.0.1' /var/log/mail.log | tail -10

# See which destinations are being refused and how often
grep 'Connection refused' /var/log/mail.log | grep -oE 'connect to [^ ]+' | sort | uniq -c | sort -rn | head

# Current deferred queue size
find /var/spool/postfix/deferred -type f 2>/dev/null | wc -l

On RHEL and CentOS systems, substitute /var/log/maillog for /var/log/mail.log.

How to diagnose it

Work through the decision tree in order. The log line tells you which path to take based on the connect to target.

flowchart TD
    A["Log shows Connection refused"] --> B{"Refused target?"}
    B -->|"127.0.0.1 port"| C["Content filter down"]
    B -->|"relayhost"| D["Test relayhost port 25"]
    B -->|"destination MX"| E{"All destinations
or one domain?"} E -->|"All destinations"| F["Port 25 egress blocked"] E -->|"One domain"| G["MX down or transport override"] C --> H{"Filter process running?"} H -->|No| I["Restart filter"] H -->|Yes| J["Check filter port config"] D --> K{"Reachable?"} K -->|No| L["Fix relayhost or remove"] K -->|Yes| M["Check transport_maps"] F --> N["Route via relay on 587 or 465"] G --> O["dig MX and inspect transport_maps"]

Step 1: Identify the refused target. Parse the connect to <host>[<ip>]:<port> field from the log line. If it is 127.0.0.1 or localhost, this is a content filter problem, not an outbound delivery problem. If it is a relayhost address, skip to step 4. If it is a destination MX, continue.

Step 2: Determine scope. Are all destinations refused, or just one domain? Extract and group the refused targets:

grep 'Connection refused' /var/log/mail.log | grep -oE 'connect to [^ ]+' | sort | uniq -c | sort -rn | head

If every destination shows Connection refused, the problem is on your side: port 25 egress is blocked, or Postfix cannot route traffic. If only one or a few domains are affected, the destination itself is the issue, or a transport_maps entry is routing those domains somewhere unexpected.

Step 3: Test port 25 egress directly. Pick a well-known MX and test TCP connectivity:

# Test TCP connectivity to a known MX on port 25
nc -w 5 -zv gmail-smtp-in.l.google.com 25

If this fails with Connection refused or times out, your server cannot reach the internet on port 25. This is almost certainly ISP or cloud provider egress filtering. AWS EC2 blocks outbound port 25 by default and no longer grants exceptions for most accounts. Many residential ISPs (Comcast, Verizon, AT&T) do the same. Check your provider’s documentation.

Step 4: Check relayhost configuration. If postconf -h relayhost returns a value, every outbound message should go through that host. Show the relayhost, then test it manually:

# Show relayhost configuration
postconf -h relayhost
# Test connectivity manually based on output, e.g.:
# nc -w 5 -zv smtp.relay.example 587

If the relayhost refuses connections, it is down or not listening on the configured port. Fix the relayhost, or temporarily remove it to allow direct delivery (if your provider does not block port 25).

Step 5: Check transport_maps overrides. If both relayhost and transport_maps are set, transport_maps takes precedence for matching domains. A transport map entry for a specific domain bypasses the relayhost entirely, causing direct connections that may be refused if port 25 egress is blocked:

# Show transport_maps configuration
postconf -h transport_maps

# Test lookups for affected domains
postmap -q example.com hash:/etc/postfix/transport

Step 6: Check content filter health. If logs show connect to 127.0.0.1[127.0.0.1]:10024: Connection refused, your content filter (typically Amavis, Rspamd, or a commercial filter) is not running or not listening on the configured port. This is not an outbound delivery problem, but it looks identical in the logs:

# Check if content_filter is configured
postconf -h content_filter

# Test the filter port directly
nc -zv 127.0.0.1 10024

# Check filter process status
systemctl status amavisd 2>/dev/null || systemctl status rspamd 2>/dev/null

Metrics and signals to monitor

SignalWhy it mattersWarning sign
Deferred queue growth rateDeferrals accumulate with exponential backoffSustained positive growth over multiple 5-minute windows
Delivery rate vs injection rateDivergence means outbound delivery is failing while mail keeps arrivingDelivery rate dropping below 80% of injection rate
Deferral reason distributionDistinguishes Connection refused from timed out, 4xx, or DNS failuresSpike in “Connection refused” as a percentage of all deferrals
Connect delay from delays= fieldSub-second means refused; approximately 30s means timed outShift from sub-second to 30s delays indicates change from port closed to port filtered
Content filter responseFilter port down appears as Connection refused to localhostAny Connection refused to 127.0.0.1
Relayhost reachabilityIf relayhost is your single outbound path, its failure blocks all mailIntermittent or sustained refusal from relayhost address

Fixes

Port 25 egress blocked by ISP or cloud provider

This is the most common cause for servers in cloud environments. AWS EC2 blocks outbound port 25 by default. Many residential ISPs do the same. The fix is to route outbound mail through a relay service on port 587 or 465.

These commands modify live Postfix configuration. Run postfix reload after applying changes. Test with a single message before flushing the queue.

# Set relayhost to a submission relay (adjust host and port)
postconf -e 'relayhost = [smtp.relay.example]:587'

# Enable SASL authentication for the relay
postconf -e 'smtp_sasl_auth_enable = yes'
postconf -e 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd'

# Create the password map
echo '[smtp.relay.example]:587 username:password' > /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db

# Reload configuration
postfix reload

This change takes effect immediately for new delivery attempts. Existing deferred messages will be retried against the new relayhost on the next scheduled attempt.

relayhost configured but not listening

If the relayhost itself is down or not accepting connections, all outbound mail stalls. Fix the relayhost service. As a temporary measure, you can remove the relayhost to allow direct delivery, but this only helps if your provider does not block port 25:

# Temporarily remove relayhost for direct delivery
postconf -e 'relayhost ='
postfix reload

Warning: if port 25 egress is also blocked (common in cloud environments), removing relayhost makes things worse, not better. Verify port 25 egress works before relying on direct delivery.

Content filter port down

If the filter process crashed or was never started after a reboot, mail queues up with Connection refused to the filter port. Restart the filter:

# Restart the content filter
systemctl restart amavisd  # or rspamd, or your filter service

In an emergency, you can bypass the filter entirely. This accepts unfiltered mail rather than queueing indefinitely:

# Emergency bypass: mail will be unscanned
postconf -e 'content_filter ='
postfix reload

Re-enable filtering as soon as the filter process is healthy.

transport_maps overriding relayhost

If transport_maps routes specific domains directly (bypassing relayhost), those domains will fail when port 25 egress is blocked. Inspect the transport map and either remove the override or point it through the relay:

# View the transport map source file
postconf -h transport_maps

# Look up routing for a specific domain
postmap -q problem.domain.com hash:/etc/postfix/transport

Fix the transport map entry, rebuild it with postmap, and reload Postfix.

Destination MX not accepting connections

If only one destination is affected, the problem is on their end. Postfix will retry per its backoff schedule. No action is needed unless the destination is business-critical, in which case consider using a backup relay or contacting the destination postmaster.

Prevention

  • Know your provider’s port 25 policy before deploying. AWS and many ISPs block outbound port 25. Plan for relay-based delivery from the start.
  • Monitor deferred queue growth rate, not just absolute size. A static queue of 5,000 messages that is shrinking is fine. The same size growing rapidly is a crisis.
  • Monitor content filter process health and response time. A filter that is running but unresponsive causes the same symptoms as one that is down.
  • Document relayhost and transport_maps dependencies. A transport_maps entry that silently overrides relayhost is easy to forget during incident triage.
  • Include port 25 connectivity tests in deployment checks. A simple nc -zv to a known MX during provisioning catches egress blocks before production traffic hits them.
  • Alert on deferral reason distribution. A spike in “Connection refused” as a percentage of deferrals distinguishes port 25 blocking from other delivery problems.

How Netdata helps

  • Per-second deferred queue depth and growth rate. The derivative (growth rate) catches queue buildup from Connection refused before it reaches crisis, and is more actionable than absolute count.
  • Mail flow velocity (injection vs delivery rate). Divergence between these two rates is the earliest indicator that outbound delivery is failing, often minutes before the deferred queue becomes visibly large.
  • Postfix log parsing for deferral reason codes. Surfaces whether the dominant error is Connection refused (port closed), Connection timed out (port filtered), 4xx responses (destination throttling), or DNS failures, determining which diagnostic path to follow.
  • Content filter process and port health. Independent checks on the filter process and its listening port catch filter outages before they manifest as Postfix delivery failures.
  • TCP connectivity probes. Tests relayhost and content filter ports independently of Postfix, confirming whether the problem is configuration or network reachability.
  • DNS resolver latency and failure rate. Rules out DNS as a contributing factor; DNS failure causes a different deferral pattern that requires a different fix.