Sending emails on port 465 in Hetzner cloud requires manual interaction

TL;DR

Using SMTP based email delivery in the Hetzner Cloud requires you to create a support ticket asking to open port 465 for all resources in your account. This must be done the first time you use it.

The port is blocked by Hetzner by default. Probably to prevent abuse.

My typical Rails Action Mailer setup

To send email in my Ruby on Rails applications, I usually use @postmarkapp and its Action Mailer integration.

All you have to do is configure Action Mailer to use the postmark delivery method.

# config/environments/production.rb
config.action_mailer.delivery_method = :postmark
config.action_mailer.postmark_settings = {
  api_token: <%= ENV['POSTMARK_API_TOKEN'] %> }
}

You can also use rails credentials instead of an environment variable

config.action_mailer.postmark_settings = {
  api_token: Rails.application.credentials.postmark_api_token
}

I use environment variables as I deploy with Kamal which loads credentials from 1Password.

Why I cannot use postmarkapp

For a video chat application that has to comply with very strict German privacy rules, I can't use postmarkapp because it's a US based service. It's a very - let's say difficult - topic, but that's the way it is.

In order to comply with data protection requirements, I had to find a European alternative to sending emails with postmark. Luckily, there is a provider that offers a transactional email service - Scaleway's Transactional Email Service (TEM).

API vs SMTP

Since there is no gem for using Scaleway's transactional email services that integrates with Action Mailer, I have to configure my application using the smtp relay server provided by Scaleway. Fortunately there is such an option.

The configuration of Action Mailer using SMTP to send emails may look familiar to you as it's no different from any other SMTP server. It looks like this:

# config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address: smtp.tem.scw.cloud
  Port: 465
  domain: med1.io
  user_name: <%= ENV['SMTP_USERNAME'] %>
  password: <%= ENV['SMTP_PASSWORD'] %>
  authentication: simple
  enable_starttls_auto: true
  tls: true
}

As mentioned above, I load the credentials from environment variables using the 1Password cli.

Switching to sending email via SMTP in the Hetzner Cloud

After making the changes and deploying the new configuration to my servers in the Hetzner Cloud, I noticed that my emails were no longer being delivered.

I was getting a connection timeout error.

Long story short ... it took me hours to find out that for new customers in the Hetzner Cloud, sending email on port 465 is not allowed by default.

You have to submit a support ticket asking for the port to be opened.

While I can understand Hetzner's reasoning behind this to protect their infrastructure from being abused, I would have liked to see some sort of notification or visual hint in their cloud console.

I searched my code for any misconfiguration, looking for the bug on my end. I also went through my Terraform setup for scaleway's email service. Everything looked fine ... I just didn't think of a network configuration problem caused by a default blocked port on the Hetzner network.

I hope Hetzner will provide a better developer experience in the future. As mentioned above, any kind of notification or banner in the firewall section would have been very helpful.

Wrapping it up

Anyway, although it was annoying and time-consuming, I learned a lot again. It's the details that matter. Find out what the real difference is that you have just made. This will help you find a solution to the problem you're stuck with.

I hope you found this article useful and that it will save you some annoying time. This is the kind of article I will be Googling myself in the future.

If you have any questions or feedback, didn't understand something, or found a mistake, please send me an email or drop me a note on twitter / x. I look forward to hearing from you.

Please subscribe to my blog if you'd like to receive future articles directly in your email. If you're already a subscriber, thank you.