Port 587 and HTTPS aren't blocked, so an app on Hetzner Cloud can send through Groundmail from day one, with no request to Hetzner:
| Your app | Use | Code change |
|---|---|---|
| You control the code | The Groundmail API or an SDK, over HTTPS | Replace the send call |
| It only speaks SMTP (Ghost, n8n, WordPress, a framework's mailer) | The SMTP relay on port 587 | None: change the SMTP settings |
Prerequisites
- A Groundmail account with a verified sending domain. A subdomain such as
mail.yourdomain.comworks well. - An API key (
gm_…) from API keys in the dashboard.
Send with the API
Give your app the key as the GROUNDMAIL_API_KEY environment variable, the same way it gets its other secrets: an .env file, a systemd unit, or your container's environment. Then send with an SDK.
Node.js
npm install groundmailimport { Groundmail } from 'groundmail'
const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY)
await groundmail.emails.send({
from: 'App <no-reply@mail.yourdomain.com>',
to: 'user@example.com',
subject: 'Reset your password',
html: '<p>Click the link to reset your password.</p>',
})Already on Nodemailer? Swap the SMTP transport for the Nodemailer transport, which sends over HTTPS, and keep your sendMail calls.
Python
pip install groundmailimport os
from groundmail import Groundmail
groundmail = Groundmail(os.environ["GROUNDMAIL_API_KEY"])
groundmail.emails.send(
from_="App <no-reply@mail.yourdomain.com>",
to="user@example.com",
subject="Reset your password",
html="<p>Click the link to reset your password.</p>",
)Go, PHP and Ruby have SDKs too: see SDKs. Any other language can call POST https://api.groundmail.dev/emails with the key: see the API reference.
Keep SMTP
If your app can only send over SMTP, point it at Groundmail's relay on port 587:
| Setting | Value |
|---|---|
| Host | smtp.groundmail.dev |
| Port | 587 |
| Encryption | STARTTLS |
| Username | groundmail |
| Password | An SMTP credential from SMTP in the dashboard |
If your app is set to port 465 (implicit TLS), change it to 587 with STARTTLS. See SMTP.
Running your apps with Coolify on a Hetzner server? See Send email from Coolify for where these settings go.
Troubleshooting
| What you see | What to do |
|---|---|
Connection timeout or ETIMEDOUT when sending |
Your app is connecting on port 25 or 465. Change the port to 587 with STARTTLS, or switch to the API. |
535 from the SMTP relay |
The username isn't groundmail, or the password isn't an SMTP credential. Create one under SMTP. |
550 saying the domain isn't verified |
The From address isn't on a verified domain. See Domains. |