That explanation from @supermathie is spot-on ![]()
The timing difference is actually useful signal, not noise.
To summarise what you’re seeing:
- 25 / 465 timing out → silent drop (Hetzner policy-level block, expected)
- 2525 connecting then immediately closing → TCP path is fine, but the remote side is terminating the session
That last one is the key detail.
Because:
- the TCP handshake succeeds
- TLS negotiation never really begins
- and it happens instantly
…it strongly suggests Mailgun is rejecting the connection early, not Discourse, Sidekiq, or Ruby.
This lines up with a few things we’ve seen recently:
- IP reputation / region-based filtering
- new Hetzner IP ranges not yet trusted
- or Mailgun-side policy checks before SMTP banner exchange
Nothing in Discourse would cause immediate remote socket closure like that - Sidekiq just hands the message off to Net::SMTP and waits.
If you want one more very strong confirmation later (no urgency at all):
openssl s_client -connect smtp.gmail.com:587 -starttls smtp
You should get a proper SMTP banner and then an auth failure - which would basically prove outbound SMTP itself is fine and Mailgun is the only endpoint behaving differently.
And completely understand pausing this - especially given the circumstances.
I’m really sorry you’re dealing with that on top of everything else ![]()
If Mailgun comes back with something useful, great - but honestly, starting fresh or switching providers (Brevo, Postmark, etc.) is often faster than waiting on SMTP reputation fixes.
You’ve already debugged this exactly the right way - nothing here suggests you missed something or misconfigured Discourse.
Safe travels to Germany, and take care.