Better Auth email with Ranla
Better Auth has a large plugin catalog (Magic Link, Email OTP, Organization, Stripe, etc.).
What it does not have is a third-party “email provider” plugin. Email delivery is always your callback:
| Surface | Callback you supply |
|---|---|
| Core email verification | emailVerification.sendVerificationEmail |
| Core password reset | emailAndPassword.sendResetPassword |
| Magic Link plugin | magicLink({ sendMagicLink }) |
| Email OTP plugin | emailOTP({ sendVerificationOTP }) |
| Organization invites | organization({ sendInvitationEmail }) |
Ranla’s integration is createBetterAuthEmail from supersendtx-better-auth: one helper that returns those callbacks, wired to POST /emails.
Better Auth’s own hosted mail (@better-auth/infra) is a separate product. This guide is for bringing your Ranla account.
Prerequisites
- Ranla account +
rnl_…API key - Verified sending domain (or Sandbox for self-tests — see Quickstart)
- Better Auth app
npm install supersendtx-better-auth @supersend/ranla better-authRANLA_API_KEY=rnl_your_key_herePublic package: supersendtx-better-auth (also available as supersendtx/better-auth from the core SDK).
Full setup (core + plugins)
// lib/auth.ts
import { betterAuth } from 'better-auth'
import { magicLink, emailOTP, organization } from 'better-auth/plugins'
import { createBetterAuthEmail } from 'supersendtx-better-auth'
const email = createBetterAuthEmail({
from: '[email protected]',
apiKey: process.env.RANLA_API_KEY!,
appUrl: process.env.BETTER_AUTH_URL, // used for invite links
})
export const auth = betterAuth({
emailVerification: {
sendVerificationEmail: email.sendVerificationEmail,
},
emailAndPassword: {
enabled: true,
sendResetPassword: email.sendResetPassword,
},
plugins: [
magicLink({
sendMagicLink: email.sendMagicLink,
}),
emailOTP({
sendVerificationOTP: email.sendVerificationOTP,
}),
organization({
sendInvitationEmail: email.sendInvitationEmail,
}),
],
})Only enable the plugins you use. Core callbacks work without any plugins.
What each callback sends
| Helper | Tag | Content |
|---|---|---|
sendVerificationEmail |
auth=verify |
Verification link |
sendResetPassword |
auth=reset |
Reset link |
sendMagicLink |
auth=magic-link |
Sign-in link |
sendVerificationOTP |
auth=otp-{type} |
One-time code (sign-in, email-verification, forget-password) |
sendInvitationEmail |
auth=invite |
Org invite link ({appUrl}/accept-invitation/{id}) |
Customize templates with email.sendAuthEmail({ to, subject, html, text, tag }) or email.sendLinkEmail(...).
Options
| Option | Default | Purpose |
|---|---|---|
from |
required | Verified sender |
apiKey |
process.env.RANLA_API_KEY |
API key |
baseUrl |
https://api.ranla.ai |
API base URL |
appUrl |
— | Base URL for organization invite links |
fireAndForget |
true |
Don’t await send in the auth request (Better Auth timing guidance). Set false in tests. |
client |
— | Inject a SuperSendTX instance |