Skip to content
Esc
  • OverviewGuidesWhat exists today, and where to start.
  • QuickstartGuidesKey, domain, first send — in that order.
  • AuthenticationGuidesBearer keys, the mandatory User-Agent, and what each refusal means.
  • ErrorsGuidesThe whole vocabulary, with the status each name carries.
  • IdempotencyGuidesRetry a send without sending it twice.
  • PaginationGuidesCursors are item IDs, not page numbers.
  • Rate limitsGuidesTen a second per team, and the headers that tell you where you are.
  • EventsGuidesEvery event a webhook can carry, with one real payload each.
  • DomainsGuidesThe records, where they go at each registrar, and what the page does while you wait.
  • TrackingGuidesOpens and clicks: one record, two toggles, and what an open really means.
  • ReceivingGuidesInbound mail, and the Inbox: a webhook fires, you read it, you answer it.
  • InboxGuidesChannels, personal mailboxes and seats: who sees what, and where a reply goes.
  • Node SDKGuidesThe rasket package: typed from the API's own document, retries only what is safe.
  • Python SDKGuidesThe rasket package on PyPI: the Node client's methods, in snake_case, over httpx.
  • MCP serverGuidesLet an assistant act on your account: your scopes, no key.
  • AI assistGuidesSubject lines, drafts and diagnosis — in the dashboard and over the API, off until you allow it.
  • AgentsGuidesLet an AI agent set Rasket up: the skill, the rules file, MCP, and the recipe they share.
  • OAuthGuidesLet another app act for a team: register, authorize with PKCE, exchange, refresh.
  • Single sign-onGuidesOIDC login for your team, a domain proved by DNS, enforcement and break-glass.
  • IntegrationsGuidesVercel, Netlify and Cloudflare: a key in the environment, or an OAuth app.
  • SMTPGuidesSend from anything that speaks SMTP: settings, setup guides, limits and replies.
  • EmailsAPI referenceSend, batch, retrieve, list, reschedule, cancel, attachments.
  • DomainsAPI referenceAdd a domain, publish its records, verify it.
  • API keysAPI referenceCreate, list, rename and revoke credentials.
  • WebhooksAPI referencePayloads, signature verification, retries and replay.
  • SuppressionsAPI referenceAddresses we will not send to, and why.
  • LogsAPI referenceEvery request made with this team's credentials.
  • MetricsAPI referenceDelivery, bounce, complaint and engagement counts.
  • TemplatesAPI referenceVersioned email content with typed variables, addressed by ID or alias.
  • ContactsAPI referenceYour audience: contacts, their typed properties, segments and topic choices.
  • SegmentsAPI referenceAudiences defined by a filter, by hand, or both.
  • TopicsAPI referenceWhat contacts subscribe to, and the preference page's list.
  • CampaignsAPI referenceCampaigns, at /broadcasts: one message to a segment, from draft to results.
  • ImportsAPI referenceCSV uploads: column mapping, conflicts and counts.
  • AutomationsAPI referenceWorkflows that run per contact: the graph, its versions, and every run.
  • Custom eventsAPI referenceThe names your product fires, and what starts a workflow.
  • ReceivingAPI referenceMail sent to you: the message, its attachments, its raw source.
  • OAuthAPI referenceClient registration, the token endpoint, and the grants a team has given.
  • TeamAPI referenceThe team a credential belongs to: its plan, sender identity, AI flag and members.
  • BillingAPI referencePlan, usage, invoices and add-ons, and the hosted pages where a customer pays.
  • AI helpersAPI referenceSubject lines, a first draft, and why an email did what it did.

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

SMTP settings
SettingValue
Hostsmtp.rasket.com
Port465 (implicit TLS) or 587 (STARTTLS)
Alternate ports2465 (implicit TLS) and 2587 (STARTTLS), for networks that block the usual two
Usernamerasket
PasswordAn 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.

How a message maps
FieldFrom the message
fromThe From: header: exactly one address
toAddresses in To: that are also envelope recipients (RCPT TO)
ccAddresses in Cc: that are also envelope recipients
bccEvery other envelope recipient. A Bcc: header is never forwarded
reply_toReply-To:
subjectSubject:
html, textThe first HTML part and the first plain-text part that are not attachments
attachmentsEvery other part. A part with a Content-ID becomes an inline attachment
headersIn-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 with 550 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

SMTP limits
LimitValueOver it
Message size4,000,000 bytes of raw message, attachments included (about 4 MB)552 5.3.4
Recipients per message50, counting To, Cc and Bcc; 10 while a new account is on its starting limits452 4.5.3 for each recipient past the limit
Sending rate10 messages a second per team, shared with the API451 4.7.1
Messages per connection100, then reconnect421 4.7.0
Connections from one address10 at a time421 4.7.0
Idle connection5 minutes between commands421 4.4.2
Failed logins3 per connection; 10 from one address in 15 minutes locks that address out for 15 minutes421 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.

SMTP replies
ReplyMeaningWhat to do
250 2.0.0Accepted: Queued as <email id>. A suppressed recipient is still accepted and shows up as an email.suppressed eventNothing
421A connection limit, a lockout after failed logins, or a restartReconnect later
451 4.7.1The rate limit, the daily or monthly quota, or the spend cap. The text says when to retryRetry; your mailer's queue holds the message
451 4.3.0, 4.3.2, 4.4.0, 4.4.2A fault or a timeout on our sideRetry. The retry replays rather than sending twice
452 4.5.3A recipient past the per-message limitSend the rest in a new message
452 4.3.1Too many messages in flight at onceRetry
454 4.7.0The login could not be checked just nowRetry
530 5.7.0MAIL FROM before logging inLog in first
535 5.7.8A wrong username, or a key that is malformed, revoked or suspendedFix the credentials
538 5.7.11A login attempted before TLSUse port 465, or turn on STARTTLS
550 5.7.1The sending domain is not verified, the key is restricted to another domain or suspended, or the account may not send this message yetChange the account or the From address
550 5.6.0The message was refused: no recipient in To:, signed or encrypted MIME, a missing From: or subject, or an invalid tagChange the message
550 5.5.3Too many recipients, when the account's limit changed while the connection was openSend fewer recipients per message
552 5.3.4Over 4 MBSend large files as a link, or use the API
553 5.1.3A recipient address that could not be readFix the address
554 5.6.0An idempotency key you already used, on a different messageUse 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 in To:; send Bcc-only mail as one message per recipient.
  • Message-ID is replaced with our own, so a client that matches its sent folder on it will not match. In-Reply-To and References are kept, so replies still thread.
  • Your own List-Unsubscribe headers 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 .ics attachment 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.