Your cloud VPS blocks SMTP. Send email over an API instead.
2026-06-26 / 6 min / email / smtp / deployment / saas / devops
A friend's freshly deployed SaaS app could not send a single email from a DigitalOcean droplet. The cause was not the code or the credentials. Cloud providers block SMTP ports by default, the failure is silent, and the fix is to send over an HTTPS email API.
I was helping a friend ship a SaaS app to a DigitalOcean droplet last week. Login worked. Payments worked. The database was healthy. Then the first user signed up and the welcome email never arrived. Neither did the password reset. Neither did anything.
There was no error in the logs that meant anything. The SMTP call did not throw a clean "auth failed" or "domain not verified." It just hung, then timed out. The app was using Zoho ZeptoMail over SMTP, the credentials were correct, the domain was verified, and the exact same config sent mail fine from a laptop.
That last detail is what makes this failure so expensive to debug. It works on your machine. It works in staging on your machine. It fails only on the server, silently, and every instinct points you at the wrong layer.
The symptom: SMTP that times out for no visible reason
I spent an evening on it. Checked the API key. Rotated it. Reverified the sending domain. Reread the ZeptoMail setup docs. Confirmed the from-address matched the verified domain. Tried port 465, then 587, then back again. Every change produced the same result: a connection that opened, waited, and died on a timeout.
When a connection times out rather than getting refused, that is rarely a credentials problem. Bad credentials get you a fast rejection. A timeout means the packets are not reaching the other side at all. So I stopped touching the app and tested the network directly from the server.
The test that ended the guessing
A few lines of connectivity checks from the droplet told the whole story:
FAILED smtp.zeptomail.com 465 TimeoutError
FAILED smtp.zeptomail.com 587 TimeoutError
OK api.zeptomail.com 443
OK google.com 443
The SMTP ports were dead. Plain HTTPS on 443 was wide open. The internet worked. Email-over-SMTP, specifically, did not.
That is not a ZeptoMail problem and it is not a code problem. It is the host.
The cause: cloud providers block SMTP by default
DigitalOcean's own docs are blunt about it. SMTP ports 25, 465, and 587 are blocked on droplets to prevent spam and abuse, and the block applies to all droplets by default, including traffic through a Reserved IP. Their recommendation is to use a third-party email service provider rather than fight the block.
This is not unique to DigitalOcean. Most major cloud and VPS providers throttle or block outbound SMTP on new accounts for the same reason: a fresh server that can blast port 25 is a spammer's favorite tool, so the safe default is closed. Your laptop sends mail because residential and office networks usually leave 587 open. Your server cannot, because the provider deliberately shut it.
So the failure has nothing to do with the thing you have been staring at. The code is fine. The credentials are fine. The transport is blocked one layer below where you were looking.
Why this one is a genuine debugging trap
A few things line up to waste your time:
- It is silent. No bounce, no rejection, just a timeout that looks like a flaky network or a slow provider.
- It works locally. Every test you run on your own machine passes, so you keep blaming the deploy rather than the host.
- The error points away from the real cause. A timeout reads as "the email provider is down" or "DNS is wrong," not "my host blocks this port."
- It only shows up in production. The app is otherwise healthy, so email feels like a small misconfiguration rather than an infrastructure policy.
This is the same shape as other production-only failures that never show up in a demo. The code is not wrong. The environment is different, and nobody tested the path that the environment breaks.
The fix: send over HTTPS, not SMTP
The clean fix is to stop sending email over SMTP from application code and use the provider's HTTP API over 443 instead. For my friend's app that meant swapping ZeptoMail's SMTP transport for a POST to https://api.zeptomail.com/v1/send with the API key in a header. Same provider, same verified domain, same templates. Different transport. Emails started flowing within minutes, because 443 was never blocked.
There are workarounds that keep you on SMTP, and they are worth knowing, but none are as clean:
- Open a support ticket asking the host to unblock SMTP. They sometimes will, for accounts with history and a clear use case. It is slow and not guaranteed.
- Use port 2525. Some providers leave it open, and many email services accept STARTTLS on it as a 587 stand-in. It works often enough to be a fallback, not a plan.
Both of those leave you depending on a port a host can close again. Sending over the API on 443 sidesteps the entire category. It is also what every major email provider now recommends as the default for application mail, because SMTP from app code carries connection state, retries, and timeout handling you do not want to own.
The broader lesson: in 2026, SMTP is the wrong default for transactional email from a deployed app. It is a mail-server-to-mail-server protocol that we kept reaching for inside application code out of habit. An HTTPS API is the better fit. It uses a port nobody blocks, it gives you real status codes instead of socket timeouts, and it hands deliverability infrastructure to someone whose job is deliverability.
Why I am building SendStack
This is the kind of avoidable, hours-eating failure that pushed me to build SendStack, a transactional email API for the apps I ship for clients, and soon a public offering.
The whole point is that the first email works on the first deploy. One HTTPS endpoint, SPF, DKIM, and DMARC verification handled, real delivery events instead of guesswork, and no SMTP ports to discover are blocked the night you launch. It started as internal tooling precisely because I kept watching good apps fail on this one boring layer, and the fix is the same every time.
If you have a deployed app that cannot send email and you are not sure whether it is your code, your provider, or your host, send a brief and I can help you find the layer that is actually broken. For deeper deployment and infrastructure work, senior engineering support covers the rest of the stack once the mail is flowing.
Read next
- Small business tech fixes that should not become rebuilds
A practical list of website, email, DNS, SSL, booking, form, M-Pesa, and AI-built app problems that can often start as a small fix before anyone quotes a rebuild.
- What to automate first in a law or accounting firm
Professional firms do not need AI everywhere on day one. A practical order for automating client intake, booking, document prep, and follow-up without breaking trust or compliance.
