GuidesSMTP
SMTP relay
Point anything that sends over SMTP at Rasket — Supabase Auth, WordPress, a framework mailer — and every message becomes the same POST /emails an API client makes.
Settings
| Setting | Value |
|---|---|
| Host | smtp.rasket.com |
| Port | 465 (implicit TLS) or 587 (STARTTLS) |
| Alternate ports | 2465 (implicit TLS) and 2587 (STARTTLS), for networks that block the usual two |
| Username | rasket |
| Password | An API key (rk_…) with full or sending access |
Use 2465 or 2587 only when a network or a hosting provider blocks the usual port; they behave the same way.
TLS is required: on port 465 the connection starts encrypted, and on 587 the login is offered only after STARTTLS. Port 25 is not offered. The login mechanisms are PLAIN and LOGIN.
Your team's settings, and a button to create the key, are in the dashboard under Settings → SMTP.
The password is an API key, so treat the setting that holds it like one. Create a key with sending access, restricted to the domain the app sends from: a leaked SMTP password can then send from one domain and do nothing else.
What stays the same
The relay is not a second way in. Each message is one request to the API, made with your key, so everything that applies to an API send applies here: the From address has to be on a verified domain, a key restricted to one domain can send only from it, suppressed addresses are skipped, and the message counts against your quota and rate limit exactly as an API call would. Delivery, bounce and complaint events reach your webhooks, and the Emails and Logs pages show the message with the source SMTP.
Setup guides
Every guide below uses port 465 and reads the key from RASKET_API_KEY. The From address in each one has to be on a domain you have verified.
Supabase Auth
In the Supabase dashboard, open Authentication, then the SMTP settings under Emails, and turn on custom SMTP. Set the sender email to an address on your verified domain, the host to smtp.rasket.com, the port to 465, the username to rasket and the password to your key, then save. Sign-up confirmations, magic links and password resets now go through Rasket.
Supabase applies an hourly limit of its own to auth email. Raise it under Authentication → Rate Limits if your sign-ups need more. For a project run with the Supabase CLI, the same settings go in supabase/config.toml:
[auth.email.smtp]
enabled = true
host = "smtp.rasket.com"
port = 465
user = "rasket"
pass = "env(RASKET_API_KEY)"
admin_email = "auth@send.acme.example"
sender_name = "Acme"Nodemailer
secure: true is what port 465 needs; on 587 set secure: false and Nodemailer upgrades with STARTTLS. The two X-Rasket- headers are optional: see headers you can add.
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: "smtp.rasket.com",
port: 465,
secure: true,
auth: { user: "rasket", pass: process.env.RASKET_API_KEY },
});
await transporter.sendMail({
from: "Acme <billing@send.acme.example>",
to: "customer@example.com",
subject: "Your receipt",
text: "Thanks for your order.",
headers: {
"X-Rasket-Idempotency-Key": "receipt-1042",
"X-Rasket-Tags": "category=receipt",
},
});WordPress
WordPress sends through PHPMailer. Any SMTP plugin will do: give it the settings above, with SSL as the encryption. Without a plugin, add this to a small plugin of your own or to the theme's functions.php. The two filters matter, because WordPress otherwise sends from wordpress@ your site's domain, which is rarely the domain you verified.
add_action('phpmailer_init', function ($mailer) {
$mailer->isSMTP();
$mailer->Host = 'smtp.rasket.com';
$mailer->Port = 465;
$mailer->SMTPSecure = 'ssl';
$mailer->SMTPAuth = true;
$mailer->Username = 'rasket';
$mailer->Password = getenv('RASKET_API_KEY');
});
add_filter('wp_mail_from', fn () => 'site@send.acme.example');
add_filter('wp_mail_from_name', fn () => 'Acme');Laravel
In .env. MAIL_SCHEME is read by Laravel 11 and later; earlier versions take MAIL_ENCRYPTION=ssl instead.
MAIL_MAILER=smtp
MAIL_SCHEME=smtps
MAIL_HOST=smtp.rasket.com
MAIL_PORT=465
MAIL_USERNAME=rasket
MAIL_PASSWORD="${RASKET_API_KEY}"
MAIL_FROM_ADDRESS="hello@send.acme.example"
MAIL_FROM_NAME="Acme"Rails Action Mailer
In config/environments/production.rb. tls: true is implicit TLS, which is what port 465 speaks. On 587, drop it and set enable_starttls_auto: true instead.
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.rasket.com",
port: 465,
tls: true,
authentication: :plain,
user_name: "rasket",
password: ENV.fetch("RASKET_API_KEY")
}Django
In settings.py, with os imported. EMAIL_USE_SSL is the setting for port 465. On 587 use EMAIL_USE_TLS instead; Django refuses both at once.
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.rasket.com"
EMAIL_PORT = 465
EMAIL_USE_SSL = True
EMAIL_HOST_USER = "rasket"
EMAIL_HOST_PASSWORD = os.environ["RASKET_API_KEY"]
DEFAULT_FROM_EMAIL = "Acme <hello@send.acme.example>"Moving from another provider
If an app sends over SMTP today, the move is three settings: the host, the username and the password. Add and verify your domain in Rasket first, and keep the old provider until the domain reads verified, because a message from an unverified domain is refused with 550 5.7.1. A mailer that already sends an idempotency header for its old provider may keep sending it: one other provider's header is accepted verbatim, as is its SMTP username, and the comparison pages say which.
How a message becomes a send
One SMTP transaction is one POST /emails. The envelope decides who receives the message and the headers decide how it looks. MAIL FROM is ignored, because the return path is ours.
| Field | From the message |
|---|---|
from | The From: header: exactly one address |
to | Addresses in To: that are also envelope recipients (RCPT TO) |
cc | Addresses in Cc: that are also envelope recipients |
bcc | Every other envelope recipient. A Bcc: header is never forwarded |
reply_to | Reply-To: |
subject | Subject: |
html, text | The first HTML part and the first plain-text part that are not attachments |
attachments | Every other part. A part with a Content-ID becomes an inline attachment |
headers | In-Reply-To, References, the priority headers and your own X- headers. Everything else a mailer adds is dropped, not refused |
To: and Cc: are rewritten to the addresses the envelope actually reaches, which is what a mailer that sends one copy per recipient expects.
Headers you can add
X-Rasket-Tags: category=receipt, plan=pro— becomes the email's tags, which come back on the email and on every webhook event for it. An invalid tag refuses the message with550 5.6.0.X-Rasket-Idempotency-Key: receipt-1042— becomes the idempotency key, so a mailer that sends the same message twice sends it once.
Without a key header, a message with a Message-ID gets one derived from it and the envelope, so a mailer that times out after the final . and sends the whole message again gets the first answer back rather than a second email. Both headers are removed before the message goes out.
Limits
| 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 |
| Failed logins | 3 per connection; 10 from one address in 15 minutes locks that address out for 15 minutes | 421 4.7.0 |
The size is counted on the message as your mailer encodes it, and base64 makes an attachment about a third larger, so files add up to a little under 3 MB. That is lower than the API's limit: a larger message has to go through POST /emails, or carry its large files as links.
Replies
A 4xx reply means try again later, and your mailer's queue will. A 5xx reply means something about the message or the account has to change first. The text after the code is the API's own error message, so a mailer's log says what the dashboard would.
| Reply | Meaning | What to do |
|---|---|---|
250 2.0.0 | Accepted: Queued as <email id>. A suppressed recipient is still accepted and shows up as an email.suppressed event | Nothing |
421 | A connection limit, a lockout after failed logins, or a restart | Reconnect later |
451 4.7.1 | The rate limit, the daily or monthly quota, or the spend cap. The text says when to retry | Retry; your mailer's queue holds the message |
451 4.3.0, 4.3.2, 4.4.0, 4.4.2 | A fault or a timeout on our side | Retry. The retry replays rather than sending twice |
452 4.5.3 | A recipient past the per-message limit | Send the rest in a new message |
452 4.3.1 | Too many messages in flight at once | Retry |
454 4.7.0 | The login could not be checked just now | Retry |
530 5.7.0 | MAIL FROM before logging in | Log in first |
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, the key is restricted to another domain or suspended, or the account may not send this message yet | Change the account or the From address |
550 5.6.0 | The message was refused: no recipient in To:, signed or encrypted MIME, a missing From: or subject, or an invalid tag | Change the message |
550 5.5.3 | Too many recipients, when the account's limit changed while the connection was open | Send fewer recipients per message |
552 5.3.4 | Over 4 MB | Send large files as a link, or use the API |
553 5.1.3 | A recipient address that could not be read | Fix the address |
554 5.6.0 | An idempotency key you already used, on a different message | Use a new key |
What it does not do
- It never sends a bounce message. After
250, what happened to a message is an event, a webhook and a row on the Emails page — never a message back to your return path. - Bcc-only mail is refused with
550 5.6.0. A message needs at least one recipient inTo:; send Bcc-only mail as one message per recipient. Message-IDis replaced with our own, so a client that matches its sent folder on it will not match.In-Reply-ToandReferencesare kept, so replies still thread.- Your own
List-Unsubscribeheaders are dropped, the same as over the API. - Signed or encrypted messages (S/MIME, PGP) are refused, because rebuilding them would break the signature.
- A calendar invite arrives as an
.icsattachment rather than an invitation. - Scheduling, templates and topics are not available over SMTP. Use the API for those.
- Addresses with non-ASCII characters before the @ are not accepted yet.