Use Scribase Mail as Supabase's mail server
Send Supabase Auth emails (sign-up confirmations, magic links, password resets) through Scribase Mail with custom SMTP or the Send Email Hook, and lift the 2-emails-per-hour default limit.
Supabase Auth sends sign-up confirmations, magic links, password resets and email-change notices. By default it sends them from a shared Supabase address, limited to 2 emails per hour, and only to addresses on your own team. For a real app you must bring your own mail provider. Scribase Mail is built for that: one domain, three DNS records, and every Supabase auth email goes out DKIM-signed from your domain, logged in your Scribase account.
There are two ways to connect. Both settings live in the Supabase dashboard under Authentication.
| Method | Supabase setting | Status | Best for |
|---|---|---|---|
| Custom SMTP | Project Settings → Authentication → SMTP Settings (/auth/smtp) | Live | Zero code. Supabase keeps rendering its own templates; we deliver them. |
| Send Email Hook | Authentication → Hooks → Send Email (/auth/hooks) | available soon | You want our templates, our logs per email_action_type, or no SMTP at all. |
Custom SMTP is live:
smtp.scribase.com, port465(TLS) or587(STARTTLS), usernamescribase, password = your API key. The hook receiver is the last piece being finished; its settings below are final, so you can prepare them today.
Before either method: verify your domain
- Create the domain and copy the records:
POST /domainswith{ "name": "yourapp.com" }(ormail.domains.createin the TypeScript SDK). - Publish the DKIM, SPF (return-path) and DMARC records at your DNS provider. See Domains and DNS.
- Run
POST /domains/{id}/verifyuntilstatusisverified. - Create an API key:
POST /api-keyswith{ "name": "supabase", "permission": "sending_access", "domain_id": "..." }. A sending-only key restricted to the domain is the right shape for a setting that lives in another vendor's dashboard.
Method A: custom SMTP
In the Supabase dashboard open Project Settings → Authentication, scroll to SMTP Settings and turn on Enable Custom SMTP. Fill the fields exactly like this:
| Supabase field (API name) | Value |
|---|---|
Sender email (smtp_admin_email) | auth@yourapp.com — must be on your verified domain |
Sender name (smtp_sender_name) | Your app's name |
Host (smtp_host) | smtp.scribase.com |
Port number (smtp_port) | 587 (STARTTLS) or 465 (implicit TLS) |
Username (smtp_user) | scribase |
Password (smtp_pass) | your API key (sk_...) |
| Minimum interval between emails | leave the default |
Save. Supabase then applies its own rate limit of 30 emails per hour for custom SMTP; raise it under Authentication → Rate Limits once your domain is verified.
The same values work through the Supabase Management API:
{
"external_email_enabled": true,
"smtp_admin_email": "auth@yourapp.com",
"smtp_sender_name": "Your App",
"smtp_host": "smtp.scribase.com",
"smtp_port": "587",
"smtp_user": "scribase",
"smtp_pass": "sk_..."
}
What happens on our side: the message is accepted on the SMTP port, authenticated by the API key, checked against the key's domain restriction, DKIM-signed, queued and delivered exactly like an API send. It shows up in GET /emails, and your email.sent / email.delivered / email.bounced webhooks fire for it. Bounced or complaining recipients are added to your suppression list automatically, which keeps your sign-up emails out of spam.
If you run Scribase Auth (the Supabase-compatible auth in your Scribase project) the same SMTP block applies; there you can also pick "Scribase Mail" from the provider list and skip the form.
Method B: Send Email Hook available soon
The Send Email Hook lets Supabase hand each email to an HTTP endpoint instead of SMTP. When the hook is enabled, "Auth Hook handles email sending (SMTP not used)". Scribase Mail exposes a receiver for it so you get our accessible templates and a log entry per email_action_type, without an SMTP password in your Supabase project.
- In your Scribase Mail dashboard open Connect Supabase and create a hook. You get a URL like
https://mail-api.scribase.com/hooks/supabase/send-email/{hook_id}and a secret in Supabase's format:v1,whsec_<base64>. - In the Supabase dashboard open Authentication → Hooks, choose Send Email, pick HTTPS, paste the URL and the secret, and enable it.
- Trigger a sign-up. The email arrives from the
from_addressof your Scribase Mail auth project; the entry appears inGET /emailstaggedcategory=supabase:signup.
What Supabase posts and what we do with it:
email_data.email_action_type | We send |
|---|---|
signup, invite | Confirm-your-email with the token_hash link and the 6-digit token |
magiclink, email | Sign-in link (and code) |
recovery | Password reset link |
email_change | Both the old and the new address get their links (token_hash and token_hash_new) |
reauthentication | Code only |
*_notification types | Plain notice; no links |
The payload is a user object plus email_data with token, token_hash, redirect_to, email_action_type, site_url, token_new and token_hash_new. We verify the Standard Webhooks headers (webhook-id, webhook-timestamp, webhook-signature) with your hook secret, reject replays, build the link as {site_url}/auth/v1/verify?token={token_hash}&type={email_action_type}&redirect_to={redirect_to}, and answer 200 with an empty JSON object so Supabase marks the email as sent.
Which one should I pick?
- You have Supabase email templates you like, or you need the change live in two minutes: custom SMTP.
- You want each auth email type logged separately, want to swap templates without touching Supabase, or your security review does not want a long-lived SMTP password in a third-party dashboard: Send Email Hook.
Either way your other transactional email (receipts, alerts, invites from your own code) goes through the same account with the API or the SDK, and sign-in without Supabase at all is one call away with magic links and OTP.
Not on Supabase but on Clerk?
Clerk sends its own emails and does not let you set SMTP. The replacement is to stop paying for Clerk's email tier and use Scribase Mail auth: POST /auth/magic-link and POST /auth/otp give you passwordless sign-in with a verifiable JWT, from your own domain, on the same bill as your database.