SMTP
Why EC2 blocks port 25, and what actually works
By default, an EC2 instance can open outbound connections on port 25 to private IPv4 addresses and nowhere else. Traffic to public IPv4 and to IPv6 on port 25 is dropped — silently, at the network layer, not by a security group you can edit.
This catches people out because everything looks correct. The security group permits it, the host firewall permits it, and the connection simply hangs.
Why the block exists
Port 25 is server-to-server mail delivery. It is also how a compromised instance sends spam, and a cloud provider with freely available instances is an attractive place to do that from. The restriction is a default on every account rather than a penalty on yours.
Note what is not blocked: submission ports. 587, 465 and 2525 are outbound without restriction. If your application hands mail to a relay, nothing here affects you. The block only matters if your server is itself delivering to recipient mail servers.
Diagnosing it properly
Test against a known-good destination and be careful about address families:
timeout 10 nc -4 -vz gmail-smtp-in.l.google.com 25
The -4 matters. Many mail hosts resolve to IPv6 first, and an instance
without IPv6 connectivity fails for that reason instead — producing a result that looks
identical to the port block. Test port 443 to the same host as a control: if 443
succeeds on IPv4 and 25 hangs, the block is real.
Requesting removal
AWS provides a form, "Request to Remove Email Sending Limitations". It asks for your use case, your elastic IP, and the reverse DNS record you want set. You must submit it yourself from the account in question.
Two things improve the odds, and both should be true before you apply:
- The reverse DNS already resolves. For an Elastic IP this is
self-service via
ec2 modify-address-attribute— no support case. AWS validates the forward A record first, so publishmail.yourdomainpointing at the IP before requesting the PTR, or the call fails. - SPF, DKIM and DMARC are published and passing. A domain with no authentication reads as speculative.
Describe a specific, existing application. Transactional mail for a named service with an estimated daily volume is a use case; "sending emails" is not.
When the request is refused
It happens, and a refusal is frequently final — the response may state that further messages on the subject will not be answered. Arguing is not a strategy. There are three routes, in descending order of how much they preserve.
Move the mail node, keep everything else. If your architecture separates the application from the MTA, only the MTA has to live somewhere that permits port 25. The API, the database and the dashboard stay on AWS. Providers that allow port 25 on request without a lengthy process do exist; the usual condition is an account in good standing and a clear description of what you are sending.
Relay through a provider. Hand mail to an established service over 587, which is unaffected. You lose direct control of the delivery path and the reputation is partly theirs, but it works immediately. Worth knowing that Amazon SES itself is reachable on 465 and 587, neither of which is throttled — so an EC2 instance can send through SES without ever touching port 25.
Use a different cloud. The port 25 position varies between providers far more than their marketing suggests. Some allow it after a short verification; some never do.
What to check before you move
Allowing port 25 is necessary and not sufficient. The IP's history matters more. A provider that permits port 25 but recycles IPs with a poor sending history will leave you warming up an address that is already on blocklists.
Before committing: check the IP against the major blocklists, confirm you can set reverse DNS yourself, and send a test to a mailbox you control at each major provider. An IP that lands in spam before you have sent anything real is not a usable IP, whatever the port policy says.
The inbox tester will score a real message end to end, which is the only check that reflects what a receiver actually sees.
DKIM signing, SPF alignment and DMARC are set up the moment you verify a domain.