Send email from Railway

Railway blocks outbound SMTP on its Free, Trial and Hobby plans. Connections to ports 25, 465, 587 and 2525 never leave Railway, so a mail library that sends through an SMTP server fails with Connection timeout, ETIMEDOUT or Network is unreachable, even when the host, username and password are right. Only Pro and above can send over SMTP.

HTTPS isn't blocked on any plan. There are two ways to send through Groundmail from Railway:

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 template, on Railway's private network None: change the SMTP settings

Prerequisites

  • A Groundmail account with a verified sending domain. A subdomain such as mail.yourdomain.com works well.
  • An API key (gm_…) from API keys in the dashboard.

1. Send with the API

Add the API key to your service's variables in Railway as GROUNDMAIL_API_KEY, then send with an SDK.

Node.js

npm install groundmail
import { 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 groundmail
import 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>",
)

Django, Rails, Laravel and Symfony have drop-in mail backends that send over HTTPS. Any other language can call POST https://api.groundmail.dev/emails with your key: see the API reference.


2. Keep SMTP: the relay template

For apps that can only send over SMTP, deploy the Groundmail SMTP relay into the same Railway project. Your app sends SMTP to the relay over Railway's private network, which isn't blocked, and the relay delivers each message over HTTPS.

your app ──SMTP (private network)──▶ smtp-relay ──HTTPS──▶ Groundmail
  1. Deploy the Groundmail SMTP Relay template into your project, and paste your API key when it asks for GROUNDMAIL_API_KEY. The template generates the relay's SMTP password.
  2. In your app's service, set its SMTP settings to the relay with reference variables:
Setting Value
Host ${{smtp-relay.RAILWAY_PRIVATE_DOMAIN}}
Port 2525
Encryption None (traffic stays on the private network)
Username ${{smtp-relay.SMTP_USERNAME}}
Password ${{smtp-relay.SMTP_PASSWORD}}
From address An address on your verified domain
  1. Redeploy your app and send a test email. It shows up under Emails in the dashboard with its delivery status.

Bcc, attachments, inline images, Reply-To and custom headers like List-Unsubscribe are kept. If Groundmail rejects a message, for example because the From domain isn't verified, your app gets a 550 with the reason.

The relay's README has the settings for Ghost, n8n, Django and Nodemailer.


On Railway Pro

Pro can reach SMTP servers directly, so you can also use the SMTP relay settings as they are: smtp.groundmail.dev, port 587, STARTTLS, username groundmail and an SMTP credential as the password. Redeploy after upgrading, since the change applies to new deployments.


Troubleshooting

Error Cause Fix
ETIMEDOUT or Connection timeout to smtp.groundmail.dev SMTP is blocked on your Railway plan Use the API, or the relay template
ENOTFOUND smtp-relay.railway.internal The relay is in a different project, or has a different service name Deploy the relay into the same project, and use its service name in the reference variable
535 Invalid username or password The app's password doesn't match the relay's SMTP_PASSWORD Use the ${{smtp-relay.SMTP_PASSWORD}} reference variable
550 … domain is not verified The From address isn't on a verified domain Verify the domain under Domains, or change the From address