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

  1. Ranla account + rnl_… API key
  2. Verified sending domain (or Sandbox for self-tests — see Quickstart)
  3. Better Auth app
npm install supersendtx-better-auth @supersend/ranla better-auth
RANLA_API_KEY=rnl_your_key_here

Public 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