SMTP relay: what it is, when you need one, and how to set one up
Published Updated 13 min readBy the Rasket team

What an SMTP relay is
An SMTP relay is a mail server that accepts a message from a client and sends it on to another server. RFC 5321, the standard that defines SMTP, describes a relay as a system that receives mail from an SMTP client and transmits it to another SMTP server without changing the message beyond adding trace information. In everyday use the word means something slightly narrower: the server your application logs in to so that it can hand over mail and forget about it.
Your application could, in principle, look up the recipient’s mail server and deliver to it directly. In practice that fails for reasons that have nothing to do with your code. The address it connects from has no sending reputation, the outbound port is often blocked, nothing signs the message for your domain, and when the receiving server says “try later” there is no queue to try later from. A relay exists to own those problems.
So the shape is always the same. Your software opens one authenticated, encrypted connection to the relay, offers the message, and gets a reply. Everything after that reply — finding the recipient’s server, retrying, signing, recording what happened — is the relay’s job.
Relay, MTA and API: three different things
The three terms get used interchangeably, and the difference matters when you are choosing what to point an application at.
- An MTA (mail transfer agent) is mail server software: the program that speaks SMTP to other servers, queues mail and retries it. Every relay is built on one. The glossary entry covers the role in more depth.
- A relay is an MTA in a particular role: it accepts mail from clients it trusts and moves it on. Strictly, the port an application logs in to is a submission service, which RFC 6409 puts on port 587 and allows to require a login and to fix up a message before it moves on. Most people call that a relay too, and so does this post.
- An email API is the same job behind an HTTPS endpoint: you POST a message as JSON and get an id back in the response. Email API vs SMTP weighs the two side by side.
An SMTP relay service is a relay someone else runs for you, with a username, a password and a domain you have proved you own. That last part is what separates it from an open relay, which accepts mail from anyone for anyone and is the reason most mail servers refuse to relay at all without a login.
When you need an SMTP relay
If you are writing the sending code yourself, an HTTP API is usually the better door: the message id comes back in the response and a retry is safe by construction. A relay is for everything that sends mail and cannot be taught to make that call.
- Auth services. Supabase Auth sends sign-up confirmations, magic links and password resets. Its built-in mail is meant for trying things out: it delivers only to addresses on the project’s team and has a small hourly cap. Production needs custom SMTP settings, and those settings are a relay.
- WordPress and other CMSs. WordPress hands mail to PHPMailer, which by default relies on the web server’s own mail setup — usually unauthenticated and from an address no one verified. Contact forms, order notifications and password resets are the mail that goes missing first.
- Framework mailers. Laravel, Rails Action Mailer, Django and Nodemailer all speak SMTP out of the box. Pointing them at a relay is a settings change; replacing them with an API call is a code change.
- Everything else that only knows SMTP. A help desk, an internal tool, a monitoring system, a printer that emails scans. None of these will learn HTTP.
In each case the value is the same: the mail comes from your own domain, signed and accounted for, rather than from whatever server the software happens to run on.
Ports, TLS and logging in
Two ports carry almost all application mail today, and they differ only in when the encryption starts.
| Port | Mode | How it starts |
|---|---|---|
| 465 | Implicit TLS | The connection is encrypted before the server says anything |
| 587 | STARTTLS | The connection starts in the clear and upgrades before the login |
| 25 | Server to server | For relays talking to each other, not for applications |
RFC 8314 recommends implicit TLS for mail submission and asks clients and servers to support both for a transition period, which is why every serious relay offers both. Pick 465 when the client supports it, and 587 when it does not or when its documentation only describes STARTTLS. Port 25 is for relays talking to each other, and many hosting networks block it outbound.
Most mailers name the setting confusingly. In Nodemailer, secure: true means implicit TLS on 465, and secure: false on 587 lets STARTTLS upgrade the connection. In Django it is EMAIL_USE_SSL versus EMAIL_USE_TLS. Setting the implicit mode on the STARTTLS port, or the other way round, is the most common reason a first connection hangs and then times out.
The login
A relay authenticates with AUTH, almost always the PLAIN or LOGIN mechanism, which send the credential as it is. That is only acceptable inside TLS, so a well-run relay refuses a login before encryption rather than letting a client leak its password on a misconfigured port.
The credential itself is the thing to think about. A mailbox password shared by every system that sends is the usual arrangement and the worst one: it cannot be scoped, and rotating it breaks everything at once. A relay that takes an API key as the password fixes both. Give each integration its own key, limit it to sending from one domain, and revoke it alone when it leaks.
What a relay does for deliverability
Moving bytes is the easy part. Whether a message reaches the inbox depends on the work a relay does around the transport, and that is what you are really choosing when you choose one.
- An authenticated domain. The relay should only send From an address on a domain you have verified, and should publish SPF and DKIM for it through records you add once. Receiving servers check those records, and a DMARC policy uses them to decide whether mail claiming to be from you really is. DKIM, SPF and DMARC explained walks through all three.
- A DKIM signature on every message. The relay signs each message with a key whose public half sits in your DNS, so a receiver can prove the message came from your domain and was not changed on the way.
- Bounce handling. When a recipient’s server refuses a message after the relay accepted it, someone has to notice. A bare relay mails a bounce to the return path and leaves the parsing to you; a relay with an API behind it turns the bounce into an event you can read.
- A suppression list. An address that hard-bounced or complained should not be mailed again, and nothing in SMTP remembers that. The relay has to, and has to enforce it on the next send even though your application never heard about the first.
None of this is in the protocol. Two relays that both accept your message on 465 can differ entirely in what happens next, so ask what a relay does after the 250, not only whether it answers one.
Limits and reply codes
Every relay has limits, and a mailer learns them from the replies. These are the ones Rasket’s relay applies, and the reply you get when you go over each one.
| Limit | Value | Over it |
|---|---|---|
| Message size | 4,000,000 bytes of raw message, attachments included (about 4 MB) | 552 5.3.4 |
| Recipients per message | 50, counting To, Cc and Bcc; 10 while a new account is on its starting limits | 452 4.5.3 for each recipient past the limit |
| Sending rate | 10 messages a second per team, shared with the API | 451 4.7.1 |
| Messages per connection | 100, then reconnect | 421 4.7.0 |
| Connections from one address | 10 at a time | 421 4.7.0 |
| Idle connection | 5 minutes between commands | 421 4.4.2 |
Base64 makes an attachment about a third larger, so the files in a message add up to a little under 3 MB. A larger file is better sent as a link in the body. The limits in the SMTP docs include the lockout rule for failed logins.
Reading a reply
An SMTP reply is a three-digit code, often followed by an enhanced status code in the class.subject.detail form RFC 3463 defines. The first digit is the part that decides what your mailer does next: 2 is success, 4 is a transient failure worth retrying, and 5 is a permanent one that will fail the same way until something changes. A mailer with a queue retries 4xx replies on its own; a 5xx reply is for a person to read.
| Reply | Meaning | What to do |
|---|---|---|
| 250 2.0.0 | Accepted, with the email's id in the text | Nothing |
| 421 | A connection limit, a login lockout, or a restart | Reconnect later |
| 451 4.7.1 | The rate limit, a daily or monthly quota, or the spend cap | Retry; your mailer's queue holds the message |
| 535 5.7.8 | A wrong username, or a key that is malformed, revoked or suspended | Fix the credentials |
| 538 5.7.11 | A login attempted before TLS | Use port 465, or turn on STARTTLS |
| 550 5.7.1 | The sending domain is not verified, or the key may not send from it | Verify the domain or change the From address |
| 550 5.6.0 | The message was refused, for example no recipient in To: | Change the message |
| 552 5.3.4 | Over 4 MB | Send large files as a link |
The text after each code is the API’s own error message, so your mailer’s log says the same thing the dashboard would. The full table has every reply the relay sends.
Setting up an SMTP relay
The procedure is the same whatever is sending. Five settings go into the client, but two things have to exist before they mean anything: a verified domain and a key.
- Add and verify a sending domain — Add the domain the mail will come from, publish the DNS records Rasket generates for it, and wait for verification to pass. The relay refuses a From address on an unverified domain with 550 5.7.1.
- Create a key for the relay — Create an API key with sending access, restricted to that domain, and store it as an environment variable. It is the SMTP password, and a leaked one can then send from one domain and do nothing else.
- Enter the relay settings — Set the host to smtp.rasket.com, the port to 465 with implicit TLS or 587 with STARTTLS, the username to rasket and the password to the key, in the client's SMTP settings.
- Set the From address — Make the client send from an address on the verified domain. Auth services and CMSs ask for a sender address separately, and some default to one on their own domain.
- Send a test message and read the reply — Send one message to an address you can read. A 250 2.0.0 reply carries the email's id; a 4xx reply means retry later and a 5xx reply means a setting or the message has to change.
- Listen for delivery events — The relay never mails a bounce back. Point a webhook at your application, or watch the Emails page, to learn which messages were delivered, bounced or complained about.
These are the settings every client below asks for, in one place:
Host: smtp.rasket.comPort: 465 (implicit TLS) or 587 (STARTTLS)Alternate: 2465 (implicit TLS) or 2587 (STARTTLS)Username: rasketPassword: an API key (rk_…) with sending accessUse 2465 or 2587 only when a network blocks the usual port; they behave the same way. Port 25 is not offered.
Keep the key in an environment variable
The password is an API key, so it belongs where your other secrets live. Every setup in the docs reads it from RASKET_API_KEY rather than writing it into a config file that ends up in version control.
Client by client
Each of these is one short block of configuration. The setup guides in the SMTP docs have the exact code for every one; what follows is what is easy to get wrong in each.
Supabase Auth
In the Supabase dashboard the settings sit under Authentication, in the SMTP settings for emails: turn on custom SMTP and fill in the sender address, host, port, username and key. Projects run with the Supabase CLI take the same values in supabase/config.toml. Supabase keeps an hourly limit of its own on auth email after the switch, so a launch day may need it raised under Authentication → Rate Limits.
WordPress
Any SMTP plugin will do: give it the settings above with SSL as the encryption. Without a plugin, a phpmailer_init hook sets the same values. Either way, set the From address too, because WordPress otherwise sends from wordpress@ your site’s domain, which is rarely the one you verified.
Nodemailer
The docs use port 465 with secure: true. If your network only allows 587, this is the variant, and verify() checks the login without sending anything:
import nodemailer from "nodemailer";
// Port 587: connect in the clear, then upgrade with STARTTLS.const transporter = nodemailer.createTransport({ host: "smtp.rasket.com", port: 587, secure: false, requireTLS: true, auth: { user: "rasket", pass: process.env.RASKET_API_KEY },});
await transporter.verify(); // logs in and logs out, sends nothingrequireTLS makes Nodemailer refuse to continue if the upgrade does not happen, rather than quietly sending the login in the clear.
Laravel
Six lines in .env. Laravel 11 and later read MAIL_SCHEME=smtps for implicit TLS; earlier versions take MAIL_ENCRYPTION=ssl instead, and setting the wrong one for your version is the usual cause of a hang on connect.
Rails
Action Mailer takes the settings in config/environments/production.rb. tls: true means implicit TLS on 465; on 587, drop it and set enable_starttls_auto: true.
Django
The SMTP email backend in settings.py. EMAIL_USE_SSL is for port 465 and EMAIL_USE_TLS is for 587; Django refuses both at once, which at least makes the mistake loud.
Checking the first message
Send one message to an address you can read and look at the reply your client logged. Success looks like this, and the id in it is the email’s id:
250 2.0.0 Queued as 4ef9a417-02e9-4d39-ad75-9611e0fcc33cThe same message is on the Emails page with the source SMTP, and every later event about it — delivered, bounced, complained — carries that id. Rasket’s relay never mails a bounce back to you: after the 250, what happened to a message is an event, a webhook and a row on that page. Point a webhook at an endpoint if you need your application to hear about it.
If nothing arrives, the reply usually says why. In rough order of how often:
- The connection times out. The port is blocked, or implicit TLS and STARTTLS are crossed. Try the alternate port, then check the TLS setting against the port.
- 535 5.7.8. The username is not
rasket, or the key was pasted with a space, revoked, or created without sending access. - 550 5.7.1. The From address is on a domain that is not verified yet, or the key is restricted to a different domain.
- Accepted, but the recipient never sees it. Look the email up on the Emails page. A recipient on the suppression list is skipped on purpose and shows up as an
email.suppressedevent rather than a refusal.
Once the first message lands, everything that sends through the relay is an ordinary send: it counts against the same quota and rate limit as the email API, and shows up in the same places. If you later want the message id in your own code rather than in a log, the API is one request away.
Frequently asked questions
What is the difference between an SMTP relay and an SMTP server?
An SMTP server is any program that speaks SMTP and accepts mail. A relay is an SMTP server in one particular role: it accepts mail from clients it trusts and passes it on to the recipient's server, rather than delivering it into a mailbox of its own. The server your application logs in to in order to send is a relay in that sense.
Should I use port 465 or port 587?
Use 465 when your client supports implicit TLS, because the connection is encrypted before anything is said and RFC 8314 recommends it for mail submission. Use 587 when the client only does STARTTLS. Both are safe when configured correctly; the mistake to avoid is setting the implicit TLS option on 587 or the STARTTLS option on 465.
What is an open relay, and why is it a problem?
An open relay accepts mail from anyone and passes it on to anyone, without a login. Spammers find them quickly, and the relay's address ends up on blocklists that stop its legitimate mail too. Every relay an application should use requires authentication over TLS, and sends only from domains the account has verified.
Can I send mail straight from my own server instead of using an SMTP relay server?
You can, and it rarely goes well. Many hosting networks block outbound port 25, a new address has no sending reputation, and you would have to run the queue, the retries, the DKIM signing and the bounce handling yourself. A relay exists so that each of those is somebody's full-time job rather than a side effect of your web server.
Why did the relay answer 250 when the email never arrived?
Because 250 means the relay accepted the message, not that the recipient's server did. Delivery happens afterwards. Look the message up by the id in the reply: it may have bounced, been deferred, or been skipped because the address is on the suppression list. Each of those is recorded as an event and can be sent to a webhook.
Is it safe to use an API key as the SMTP password?
It is safer than a shared mailbox password, provided the key is treated as a secret. Create one key per integration with sending access only, restrict it to the domain that integration sends from, and keep it in an environment variable. If it leaks, revoke that one key and nothing else stops working.
Do I still need an email API if I use an SMTP relay service?
Not to send. Over Rasket's relay each message becomes the same send an API call makes, with the same domain checks, suppression list, quota and events. The API is worth adding when your own code sends and you want the message id in the response, or features the relay does not carry, such as scheduling and templates.
Sources
- RFC 5321: Simple Mail Transfer Protocol — IETF, read 2026-10-01
- RFC 6409: Message Submission for Mail — IETF, read 2026-10-01
- RFC 8314: Cleartext Considered Obsolete: Use of Transport Layer Security (TLS) for Email Submission and Access — IETF, read 2026-10-01
- RFC 3463: Enhanced Mail System Status Codes — IETF, read 2026-10-01
- Send emails with custom SMTP — Supabase, read 2026-10-01
- SMTP Transport — Nodemailer, read 2026-10-01
Related
- SMTP — Send from anything that speaks SMTP: settings, setup guides, limits and replies.
- Email API — Send email over one REST call: idempotent sends, batches, scheduling, attachments, templates and a delivery timeline for every message.
- Email API vs SMTP: which should you use? — SMTP is a conversation; an email API is one request. What each gives you on retries, idempotency, events and firewalls, and how to move from one to the other.
- SMTP — SMTP is the protocol mail servers use to hand messages to one another. It is a conversation of short commands and numeric replies: who the message is from,…
- MTA (mail transfer agent) — An MTA is a program that moves email between servers. It accepts a message, decides where it should go next by looking up the recipient domain's MX record,…
- STARTTLS — STARTTLS is the SMTP command that upgrades a plain connection to an encrypted one. The receiving server advertises support, the sender asks to upgrade, and…