You set up Postfix or Exim on a fresh VPS, fired off a test email, and... nothing. No error, no bounce, just silence. Nine times out of ten, the culprit isn't your mail server config at all - it's port 25 being blocked somewhere between your VPS and the internet.
Symptom
The mail command hangs or times out instead of failing fast. Running telnet mail.example.com 25 from your VPS just sits there spinning. Your app queues mail successfully (it shows up in mailq or the Exim queue) but delivery never happens, and log entries show connection timeouts rather than a clean rejection like "550 relay denied."
This is different from a DNS or authentication problem. If DKIM or SPF were the issue, you'd see a clear rejection from the receiving server. A hard timeout with no response at all almost always means a network-level block on port 25, not an application-level one.
Why This Happens
Most major cloud providers - AWS EC2, DigitalOcean, Google Cloud, Azure, Oracle Cloud, Vultr, Linode - block outbound traffic on port 25 by default on new accounts and fresh VPS instances. It's not a bug, it's deliberate: port 25 is the classic spam-relay port, and providers block it preemptively to keep their IP ranges off blocklists before anyone even gets a chance to abuse it.
This is separate from Getwebup VPS firewall rules (UFW/CSF) you may have configured yourself. Even with a wide-open firewall on your own server, the block can still happen upstream at the provider's network edge, which is why ufw status or iptables -L showing everything allowed doesn't rule this out.
How to Confirm It's Actually Port 25
Run this from your VPS to test connectivity to a known-good mail server on port 25:
telnet smtp.gmail.com 25
# or, if telnet isn't installed:
nc -zv -w 5 smtp.gmail.com 25If that hangs or times out but the same command against port 587 or 465 connects immediately, you've confirmed it's a provider-level block on 25 specifically, not a general network problem.
nc -zv -w 5 smtp.gmail.com 587A successful connect on 587 while 25 times out is the signature of this exact issue.
The Fix
Option 1: Request the Block Removed (Provider-Dependent)
Some providers will unblock port 25 on request, usually after you've had the account for a while and it's in good standing:
- DigitalOcean - submit a support ticket asking to lift the port 25 restriction; they generally approve for established accounts not flagged for abuse.
- AWS EC2 - fill out the Request to Remove Email Sending Limitations form in the support console. Approval isn't guaranteed, especially for new accounts.
- Google Cloud - port 25 outbound is blocked with no unblock option for standard instances; you have to use an alternate port or relay.
- Vultr / Linode - support tickets work for aged accounts with a clear use case.
If your provider flatly refuses (Google Cloud in particular), skip straight to Option 2.
Option 2: Use Port 587 or 465 Instead (Recommended)
This is the fix that works regardless of provider policy. Instead of your mail server talking directly on port 25, route outgoing mail through an authenticated SMTP relay on port 587 (STARTTLS) or 465 (implicit TLS). Options that work well from a VPS:
- Your Getwebup cPanel/WHM mail service, if you're also hosting email there
- A transactional email provider (SES, Mailgun, SendGrid, Postmark) for app-generated mail
- Your existing Google Workspace or Microsoft 365 SMTP relay, if that's where your business mail already lives
To relay through an external SMTP server with Postfix, edit /etc/postfix/main.cf:
relayhost = [smtp.yourrelay.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
header_size_limit = 4096000Create the credentials file and secure it:
echo "[smtp.yourrelay.com]:587 username:password" > /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
systemctl restart postfixTest with:
echo "Test body" | mail -s "Relay test" you@example.com
tail -f /var/log/mail.logYou should see the message hand off to the relay and get accepted, with no timeout.
Option 3: Skip Self-Hosted Mail Entirely
If this VPS is just running an application (WordPress, a custom app, a script) that occasionally needs to send transactional email, don't run your own MTA at all. Point the app's SMTP settings directly at a relay provider's API or SMTP endpoint on port 587. It sidesteps the port 25 issue completely and usually gets you better deliverability than a fresh VPS IP would anyway, since a brand-new IP has no sending reputation.
Prevention
- Before you architect anything around self-hosted mail on a new VPS, check the provider's port 25 policy - it varies a lot and some (Google Cloud) never lift it.
- Default to an authenticated relay on port 587 for any application mail. It's more portable across providers and doesn't depend on manual unblock requests.
- If you do get port 25 unblocked and run your own MTA, still set up SPF, DKIM, DMARC, and a matching PTR record - lifting the port block only gets your mail out the door, it doesn't make receiving servers trust it.
- Keep an eye on
mailq(Postfix) orexim -bp(Exim) periodically - a growing queue with old timestamps is often the first sign mail is stuck, before you'd otherwise notice.