Resend Railway SMTP Gateway
High-throughput Go SMTP-to-Resend HTTPS relay with DDD architecture & TLS
Modern transactional email services like Resend are fast, developer-friendly, and reliable. However, they only accept messages through modern web APIs (HTTPS). Meanwhile, countless popular developer tools, internal servers, and self-hosted apps (like Infisical, GitLab, or legacy backends) only know how to send email through traditional SMTP email ports.
Because of this mismatch, teams were forced to rewrite their apps or set up heavy, complicated mail servers just to send simple login notifications and alerts.
To solve this, I built Resend Railway SMTP Gateway, an open-source Go microservice that accepts standard SMTP email traffic and translates it into Resend API calls in milliseconds, ready to run on Railway and Docker.
Here is an understanding of what was broken, how I fixed it, and the results.
§Connecting Traditional Mail Systems to Modern Web APIs in Milliseconds
When existing software only supports SMTP, connecting to a modern HTTP-only email provider usually requires installing third-party plugins, writing custom wrappers, or maintaining heavy email software like Postfix.
To bridge this gap cleanly:
- ›I built a lightweight Go service that listens for incoming SMTP connections on private ports and forwards them directly to Resend's HTTPS API.
- ›I made the relay process fast, completing the entire translation and delivery step in under 40 milliseconds.
- ›I added clear security checks with username and password verification (SMTP AUTH) so unauthorized computers on the network cannot abuse the relay.
- ›I added an optional sender domain filter so companies can restrict sending strictly to their own company domains (like
example.com).
Because of this, any tool or app that can send traditional email can now use Resend instantly without changing a single line of application code.
§Stopping Lost Emails During Traffic Spikes
When an app suddenly sends hundreds of emails at once, third-party email providers may temporarily slow down requests (returning 429 Rate Limit or 500 Server Error). If a mail server simply gives up on error, critical emails like password reset links or invoice receipts get lost permanently.
To make delivery bulletproof:
- ›I built an automatic retry system with exponential backoff and random jitter, giving the provider time to recover instead of hammering the servers.
- ›I made the gateway honor
Retry-Afterheaders, meaning it waits the exact number of seconds requested by Resend before trying again. - ›I mapped errors to correct email protocol codes: temporary internet hiccups tell the sending app to try again shortly (SMTP
4xx), while bad email addresses bounce immediately (SMTP5xx).
This ensures zero dropped emails even during sudden traffic spikes, keeping delivery trustworthy for users and businesses.
§Handling Complex Emails and Attachments Without Crashing
Emails come in many shapes and sizes: plain text, rich HTML newsletters, embedded company logos, PDF invoices, and multiple recipients (CC, BCC, Reply-To). Poorly written email parsers often crash or choke on big files.
To handle any email safely:
- ›I built a streaming MIME parser that reads email bodies, headers, and file attachments piece by piece without loading huge files into memory all at once.
- ›I added full support for multipart emails, so users on older email apps see clean plain text while modern inboxes display beautiful HTML.
- ›I preserved custom email headers, reply-to addresses, and attachment filenames so messages look exactly as the sender intended.
This eliminated crashes from large attachments and guaranteed that complex emails render cleanly across all devices.
§Automatic Security with Zero Setup Headache
Setting up SSL/TLS security certificates for internal email gateways is tedious. Developers often spend hours creating certificate authorities, configuring keys, or turning off security altogether just to get local connections working.
To make secure connections effortless:
- ›I built automatic encryption (STARTTLS) that generates a secure temporary certificate when the server starts up, requiring zero extra files.
- ›I also gave developers the option to plug in their own production SSL certificates with simple environment variables when deploying publicly.
- ›I added privacy-safe logging that records delivery speeds, message IDs, and recipient domains, but intentionally never logs private email contents or sensitive passwords.
This provides out-of-the-box encryption with zero setup headaches while keeping customer communication completely private.
§Keeping the Server Healthy on Cloud Hosting (Railway)
When hosting microservices in the cloud, platforms like Railway need a way to check if an app is still healthy. If an email service only listens on an SMTP port, cloud platforms cannot check its health and may assume it has crashed.
To make cloud deployment seamless:
- ›I built a dedicated health check server that answers
GET /healthwith200 OKon a separate HTTP port while the SMTP service stays private. - ›I added a built-in command-line healthcheck (
./resend-railway-gateway healthcheck) that Docker uses automatically to restart the container if anything goes wrong. - ›I set up graceful shutdowns so when the server needs to update or restart, it finishes sending all in-progress emails before safely closing.
This allows teams to deploy the gateway on Railway or Docker in minutes with automatic restarts and zero downtime.
§Organized Architecture That Stays Easy to Maintain
When backend tools grow quickly, mixing network logic with business rules creates spaghetti code that breaks whenever an API changes.
To keep the codebase clean and modular:
- ›I separated the code into clear layers following Clean Architecture and Domain-Driven Design (DDD).
- ›The core email rules (
internal/domain) are completely isolated from the SMTP network server and the Resend API client. - ›If a team ever wants to swap Resend for another email provider in the future, they only need to change one small adapter file without touching any core logic.
Because of this clean structure, the codebase is easy to test, simple to extend, and reliable to run in production.