Inbound email operations
Port 25 failure on initial deployment
When port 25 fails during an initial inbound-mail deployment, find the earliest broken hop with measurable checks, then roll back safely.

On an initial inbound-mail deployment, port 25 connectivity failure usually means the earliest hop cannot accept SMTP from the internet—or your provider blocks outbound 25 for abuse control. Find the first failing layer with measurable checks (DNS MX, A/AAAA, listener, firewall, provider policy), fix or roll back that layer only, and keep claims scoped to what you verified. This runbook is for operators of authorized receive pipelines—not for bypassing anyone else’s filters.
Under receive email infrastructure. Mailby product inboxes already receive for you via Quick Inbox; this article is for teams standing up their own MX. We do not expose internal Mailby ops panels.
Initial deployment context and boundaries
First deploy often includes: DNS MX → load balancer → SMTP daemon → spam filter → app store.
Common confusion: cloud VMs frequently block outbound port 25 by default. That breaks sending; inbound listen on 25 is a different path but can still be firewalled. AWS and others document SMTP port restrictions—see e.g. AWS Knowledge Center on port 25 (rel="nofollow noopener") for the outbound case; apply the same “read your provider’s mail policy” habit for inbound security groups.
Boundaries:
- Authorized systems only.
- No open relay. Receive-only or authenticated submit.
- Temporary consumer inboxes are not a substitute for fixing MX—but developers can help app tests while infra is down.
Field demonstration (editorial, 2026-09-24)
Working path: New VM security group allows TCP 25 from 0.0.0.0/0 (or preferred smarthost ranges); ss -ltn shows :25; external nc -vz mx.example 25 gets SMTP banner; MX points to correct A record.
Failure path: MX correct, local daemon listens on 127.0.0.1:25 only. External connect times out. Earliest failing hop: bind address / firewall—not DNS.
Limitation: we cannot reproduce every cloud image; always capture your own tcpdump/nc evidence.
Mechanism
Traffic path: sender MTA → your MX host:25 → daemon → pipeline.
Failures:
- MX / A mismatch
- No process on 25
- Bound to localhost
- Security group / nftables drop
- Provider network ACL
- TLS-only misconfig rejecting clear banner probes (less common on first hop)
Layer table
| Layer | Check | Expected observation | Failure clue | Rollback |
|---|---|---|---|---|
| DNS MX | dig MX example.com | Priority → intended host | Wrong host / no MX | Restore prior MX TTL |
| Address | dig A mxhost | Public IP of box | Stale IP | Fix A/AAAA |
| Listener | ss -ltn | grep :25 | LISTEN on 0.0.0.0 or :: | Missing / localhost only | Restart with correct bind |
| Firewall | Cloud SG + host fw | Allow 25/tcp | Timeout no banner | Revert SG rule |
| Banner | nc -vz host 25 | 220 response | Timeout/RST | Previous AMI / LB |
| App store | Send test message | Queued in app | Accepted then dropped | Disable new filter rule |
Worked example
Deploy checklist:
- Snapshot DNS records before change.
- Bring up daemon on staging IP; verify banner externally.
- Lower MX TTL beforehand; swap MX.
- Send test from an external account you control.
- If port 25 blocked by cloud policy, open a support request or use a relay/inbound provider—do not “clever” tunnel around ToS.
While infra is broken: developers can still validate app templates with Laravel mail tests and manual inbox receives.
Alternatives
- Managed inbound (Postmark inbound, SES receipt rules, etc.)
- Mailby for product/QA receive without self-hosting MX
- Dual-MX with vendor backup during cutover
Short answers
What causes port 25 connectivity failure on initial deployment?
DNS mistakes, bind/firewall issues, or provider blocks—verify in that order.
What should I do first?
External banner check to the MX host; then ss and security groups.
When is a permanent address safer?
Irrelevant to ops MX—but user-facing recovery still needs durable mailboxes.
What evidence changes the recommendation?
Banner OK but app empty → shift diagnosis to filtering/storage, not port 25.
Sources, test date, limitations
- Runbook date 2026-09-24.
- Provider example: AWS port 25 guidance.
- SMTP base: RFC 5321.
- Limitation: legal/ToS constraints on mail ports vary by host.
Outbound versus inbound: stop mixing the symptoms
Teams often paste “port 25 blocked” from a sending blog while debugging inbound MX. Clarify:
- Outbound 25 — your app or MTA cannot send to the world (common cloud throttle).
- Inbound 25 — the world cannot deliver to your MX listener.
Fixes differ. Outbound may require provider approval or a submission port (587) to a smarthost. Inbound needs public listen + DNS. Applying an outbound ticket to an inbound outage loses a day.
Load balancers and PROXY protocol surprises
If SMTP sits behind an L4 load balancer, health checks must speak SMTP or TCP correctly. Misconfigured health checks flap backends; external nc sometimes succeeds to the VIP while sessions reset mid-DATA. Capture packet timelines before blaming Postfix configs.
IPv6 partial deploys
MX returns AAAA, but the daemon listens only on IPv4. Some senders prefer AAAA and fail; others succeed on A. Symptom: “intermittent delivery.” Check both stacks with nc -vz on each address family.
How this differs from the receive-email-infrastructure hub
The hub describes architecture options. This runbook is a first-deploy port 25 diagnosis with layer table and rollback column. It refuses to disclose Mailby internal panels; use public product receive instead when you do not want to operate MX.
Safe rollback drill
Practice once on staging:
- Lower TTL days before cutover.
- Keep previous MX host warm.
- On failure, switch MX back before changing code.
- Only then iterate firewall/daemon.
DNS mistakes propagate longer than process restarts. TTL discipline is the real rollback mechanism.
Observability minimum viable set
- External synthetic: banner check every minute
- Internal: queue depth after accept
- Alert: zero accepts after MX change
- Log: reject codes with categories (policy, space, virus)
Without synthetics, users become your monitors—usually on launch day.
When not to self-host inbound
If the business need is “see OTPs for our SaaS,” prefer app-level testing and developers rather than standing MX on a single VM. Self-host when inbound mail is the product or a regulated requirement—not as a weekend detour.
TLS on port 25 versus submission
STARTTLS on 25 is common for MTA-to-MTA. Do not confuse it with client submission on 587. First-deploy banner checks can use cleartext 220 responses; deeper tests should negotiate STARTTLS and verify certificates match the MX hostname. Certificate mismatches cause silent sender deferrals that look like “connectivity” while TCP works.
Greylisting during cutover
New MX hosts may greylist unknown senders, delaying first messages. Coordinate with monitoring so greylisting is not paged as port failure. Document expected first-delivery delay in the runbook.
Capacity and accept rates
Port open ≠ ready for production volumes. Load-test SMTP accepts before MX cutover. A single-threaded debug daemon will pass nc and fall over under real senders.
Packet capture etiquette
Capture on the MX host with filters for port 25 only, time-box to five minutes, and avoid retaining payloads longer than needed. Redact in tickets. Connectivity diagnosis rarely needs DATA-phase content—banner and TCP handshake usually suffice.
Multi-homed hosts
Servers with multiple NICs may bind SMTP to an internal interface while DNS points to a public IP. ss shows LISTEN, external nc times out. Confirm the listen address matches the announced IP. Container port publishes (-p 25:25) fail the same way when forgotten.
Change management template
Change: MX cutover to mx2
Checks before: dig, ss, nc banner, synthetic send
Checks after: same + accept logs non-zero
Rollback: MX back to mx1 within 15 minutes if synthetic fails
Owner: @oncall
Paste into the incident channel before you start. Improvisation is how TTL mistakes become weekend work.
Relationship to product receive
If your actual goal is temporary addresses for customers or QA, do not build MX—use inbox / developers. This runbook is for teams who truly must accept mail at their domain.
DNSSEC and middlebox failures
Rare but ugly: DNSSEC misconfiguration makes MX lookups fail for validating resolvers while your laptop’s resolver succeeds. Test with a validating resolver or online DNSSEC checkers before blaming firewalls. Middleboxes that “helpfully” proxy SMTP can also break STARTTLS—compare paths on and off corporate VPN.
Runbook ownership
Assign a primary and secondary owner. Store the layer table in the ops wiki with last-exercised date. A runbook never practiced is fiction; schedule a quarterly game day that intentionally breaks staging port 25 and times the recovery.
SELinux and container capabilities
Hardened hosts may deny bind to 25 without policies. Check audit logs when ss shows nothing after a “successful” start. Containers may need NET_BIND_SERVICE or an explicit port map. These failures present exactly like “cloud blocked 25” until you read the audit line.
Appendix: quick command strip
dig +short MX example.com
dig +short A mx.example.com
ss -ltn | grep ':25'
nc -vz mx.example.com 25
sudo tcpdump -ni eth0 port 25 -c 20
Run in order. Stop at first unexpected result. Paste outputs into the incident thread with timestamps. This strip is deliberately boring; boring restores mail.
Post-incident review prompts
- Which layer failed first, really?
- Did TTL planning save us or slow us?
- Were synthetics loud enough?
- Did anyone “fix” the wrong plane (outbound vs inbound)?
- What single checklist line would have caught it in five minutes?
Write answers within 48 hours while memory is fresh. Update the layer table. Then schedule the next game day so the update is practiced, not only filed.
Coordination with security teams
Opening port 25 invites scanners within minutes. Tell security before the SG change, enable rate limits and banner greylisting as policy allows, and monitor for open-relay tests. An inbound receive pipeline that accidentally relays outbound will get your IP blacklisted—connectivity “success” followed by reputation failure. Keep relay disabled; verify with explicit anti-relay tests in the deploy checklist.
Conclusion
Port 25 failures are earliest-hop problems until proven otherwise. Measure DNS, listen, firewall, banner—then roll back the last change. Self-host only if you need to; otherwise ship product mail tests via developers and user trials via inbox while infrastructure stabilizes.
Try it on Mailby
Open a receive-only disposable inbox when a short-lived address fits the job — session-bound, with timed purge.
