An SMTP failure that happens before the AUTH step is a connectivity problem, not a credentials problem. The distinction matters because the fixes have nothing in common: a timeout is almost always a blocked port or a firewall, a refusal means nothing is listening, and a hang right after connecting usually means the encryption setting does not match the port. This guide works through them in the order that resolves the most cases fastest.
Step 1 — Identify Exactly Where It Stops
Before touching configuration, find the failing step. Every fix below depends on knowing whether you failed to resolve DNS, failed to open a socket, or failed to negotiate TLS.
# 1. Does the hostname resolve at all?
dig +short smtp.example.com
# 2. Can you open a TCP connection? (-w 5 = give up after 5 seconds)
nc -zv -w 5 smtp.example.com 587
# 3. Does the server greet you? Expect: 220 smtp.example.com ESMTP
timeout 10 openssl s_client -connect smtp.example.com:587 -starttls smtp -crlfInterpret the results directly. No DNS answer means the problem is name resolution, not mail. nc hanging until the timeout is a blocked port. nc returning "Connection refused" instantly means the port is reachable but closed. A successful nc followed by an openssl failure isolates the problem to TLS.
Step 2 — Rule Out a Blocked Outbound Port
This is the most common cause by a wide margin. Almost every consumer ISP, and most cloud and hosting providers, block outbound port 25 to limit spam. The block is silent — packets are dropped rather than rejected — which is precisely why it presents as a timeout rather than an error.
# Compare the three ports. If 25 hangs but 587 connects, it is an ISP/provider block.
nc -zv -w 5 smtp.example.com 25
nc -zv -w 5 smtp.example.com 587
nc -zv -w 5 smtp.example.com 465If 587 or 465 works and 25 does not, stop looking at your mail configuration — move the client to the submission port. Port 25 is for server-to-server transport; client software should never have been using it.
Step 3 — Match the Encryption Mode to the Port
A mismatch here produces the most confusing symptom of all: the TCP connection succeeds, then the session hangs until it times out. Each side is waiting for the other to speak first, because one expects TLS immediately and the other expects plain text.
| Port | Correct encryption | What happens if you get it wrong |
|---|---|---|
587 | STARTTLS — connect plain, then upgrade | Forcing implicit TLS hangs waiting for a TLS server hello |
465 | Implicit TLS — encrypted from the first byte | Sending plain-text EHLO produces garbage or a hang |
25 | Plain, optionally upgraded with STARTTLS | Rarely the encryption — usually the port block from Step 2 |
2525 | STARTTLS — an alternate submission port | Same as 587; only offered by some providers |
Verify each mode with the matching openssl invocation — note that they differ:
# Port 587 — STARTTLS upgrade (note the -starttls smtp flag)
openssl s_client -connect smtp.example.com:587 -starttls smtp -crlf
# Port 465 — implicit TLS (no -starttls flag; TLS starts immediately)
openssl s_client -connect smtp.example.com:465 -crlfIn application settings this is the difference between SSL and TLS in a dropdown, or between secure: true and secure: false in Nodemailer. The naming is inconsistent across libraries, so trust the port, not the label.
Step 4 — Confirm the Hostname and Its DNS
A hostname that does not resolve, or resolves to the wrong thing, produces a timeout that looks identical to a firewall problem. Two mistakes account for most of these.
Using the MX host as a submission server
The server named in your MX record receives mail for your domain. It is frequently not the server you submit outbound mail through, and it often does not accept authenticated submission at all. Google Workspace is the clearest example: mail arrives at aspmx.l.google.com but you send through smtp.gmail.com. Use the submission hostname your provider documents.
An IPv6 address that goes nowhere
If the host publishes an AAAA record and your network has broken or partial IPv6, the client tries v6 first and stalls before ever attempting v4. This produces a long hang followed by success on retry, or an intermittent timeout that nobody can reproduce.
# What does the submission host actually resolve to?
dig +short smtp.example.com A
dig +short smtp.example.com AAAA
# Force each family to see whether one of them is the problem
nc -4 -zv -w 5 smtp.example.com 587
nc -6 -zv -w 5 smtp.example.com 587If v4 connects and v6 hangs, either fix IPv6 egress or pin the client to IPv4 — most libraries expose a family option, and Postfix has inet_protocols = ipv4.
Step 5 — Check Firewalls and Egress Rules
If the port is not blocked upstream and DNS is correct, the block is closer to home. Work outward from the host:
# Local host firewall — Linux
sudo ufw status verbose
sudo iptables -L OUTPUT -n -v | grep -E "25|465|587"
# Is anything intercepting outbound traffic? Compare the two:
curl -sS -m 5 -v telnet://smtp.example.com:587 2>&1 | head -5- Cloud security groups — AWS security groups and NACLs, GCP firewall rules and Azure NSGs all need an explicit egress allow for the SMTP port on many hardened setups.
- Container networking — a container on a restricted network, or one behind a service mesh with egress policy, will time out while the host itself connects fine.
- Corporate proxies and TLS inspection — an intercepting proxy can accept the TCP connection and then fail the TLS handshake with a certificate your client does not trust.
- The provider's own IP allowlist — some relays only accept connections from registered addresses, and drop everything else silently.
Step 6 — Fix TLS Handshake Failures
If TCP connects and the greeting arrives but the session dies during negotiation, you have a TLS problem. The openssl output names the cause directly:
openssl s_client -connect smtp.example.com:587 -starttls smtp -crlf
# Look for these lines in the output:
# Protocol : TLSv1.3 ← negotiated version
# Cipher : TLS_AES_256_GCM_SHA384
# Verify return code: 0 (ok) ← anything else is a certificate problem- Protocol version mismatch — servers that have disabled TLS 1.0/1.1 will drop older clients. Conversely, a very old server may not support TLS 1.2, and a modern OpenSSL will refuse it. Update the client library or the server, in that order of preference.
- Certificate verification failure — a self-signed or expired certificate, or a missing intermediate. Check the chain with a chain checker; disabling verification is a last resort and should never be permanent.
- Hostname mismatch — the certificate does not cover the name you connected to. Connect using the name on the certificate.
- No shared cipher — a hardened server and an old client have no cipher suite in common. This appears as
no cipher matchor a handshake failure alert.
A certificate problem you cannot fix on the server side is worth confirming independently before you start weakening client settings — run an SSL check against the mail host and see whether the chain is genuinely broken or just missing an intermediate.
Step 7 — Raise Application Timeouts Last
Only once the connection is provably working should you look at timeout values. Increasing a timeout does not fix a blocked port — it just makes the failure take longer. Where it genuinely helps is a slow-but-working server, particularly one doing a reverse DNS lookup on your connecting IP before it greets you.
// Nodemailer — separate timeouts for connect, greeting and socket
const transporter = nodemailer.createTransport({
host: 'smtp.example.com',
port: 587,
secure: false, // false for 587 STARTTLS, true for 465 implicit TLS
connectionTimeout: 10000, // TCP connect
greetingTimeout: 10000, // waiting for the 220 banner
socketTimeout: 20000, // inactivity once connected
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
});Quick Reference
| Symptom | Most likely cause | First thing to try |
|---|---|---|
| Hangs on port 25, works on 587 | ISP or cloud provider blocks port 25 | Move the client to 587 |
| Connects, then hangs with no banner | Encryption mode does not match the port | STARTTLS on 587, implicit TLS on 465 |
| Connection refused immediately | Nothing listening — wrong host or port | Recheck the submission hostname |
| Works from laptop, times out from server | Cloud egress rule or container network policy | Check security groups and egress rules |
| Intermittent long hangs | Broken IPv6 path tried before IPv4 | Test with nc -6, then pin to IPv4 |
| Banner arrives, TLS then fails | Protocol, certificate or cipher mismatch | Read the openssl s_client verify code |
Frequently Asked Questions
Why does port 25 time out when 587 works fine?
Your ISP or hosting provider is blocking outbound port 25 to limit spam, and the block drops packets silently rather than rejecting them — which is why it presents as a timeout. This is normal and expected. Port 587 is the submission port and is what client software should use anyway.
Should I use port 465 or 587?
Either is fine when paired with the right encryption mode. Port 587 with STARTTLS is the most widely supported and is what most providers document. Port 465 with implicit TLS is marginally simpler because encryption is never optional — there is no plain-text window to downgrade. Pick whichever your provider recommends and set the encryption to match.
My connection works locally but times out from my server. Why?
Almost always an egress restriction that exists on the server and not on your machine — a cloud security group, a container network policy, or a host firewall. Cloud providers in particular block outbound 25 by default. Test with nc from the sending host itself to confirm.
Is a connection timeout ever caused by wrong credentials?
No. Credentials are only sent at the AUTH step, which happens after the connection is open and TLS is negotiated. If the session never reaches AUTH, the credentials have not been evaluated at all. A credential problem produces a 535 5.7.8 reply, not a timeout.
Why does the server take 30 seconds to send its greeting?
The receiving server is usually running a reverse DNS or blocklist lookup on your connecting IP before it greets you, and that lookup is timing out. Publishing a valid PTR record for your sending IP normally removes the delay. Raising the greeting timeout is a workaround, not a fix.