Example Docs

Email Verification

Email verification ensures users own the email addresses they sign up with. This is critical for account recovery, preventing spam, and building trust.

Enable Email Verification

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
  },
  emailVerification: {
    sendOnSignUp: true,
    autoSignInAfterVerification: true,
    sendVerificationEmail: async ({ user, url, token }) => {
      await sendEmail({
        to: user.email,
        subject: "Verify your email",
        html: `<a href="${url}">Click here to verify your email</a>`,
      });
    },
  },
});

How It Works

  1. User signs up with email and password
  2. Better Auth generates a verification token
  3. Your sendVerificationEmail function sends the email
  4. User clicks the link, which hits /api/auth/verify-email?token=...
  5. Better Auth verifies the token and marks the email as verified
  6. User is optionally auto-signed in
Sign Up → Generate Token → Send Email → User Clicks → Verify → Done

Configuration Options

OptionTypeDefaultDescription
sendOnSignUpbooleantrueSend verification email on sign up
autoSignInAfterVerificationbooleanfalseAuto sign-in after verification
expiresInnumber3600Token expiry in seconds (1 hour)

Custom Email Templates

With React Email

import { render } from "@react-email/render";
import { VerificationEmail } from "./emails/verification";

export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ({ user, url }) => {
      const html = render(<VerificationEmail name={user.name} verificationUrl={url} />);

      await resend.emails.send({
        from: "noreply@yourapp.com",
        to: user.email,
        subject: "Verify your email address",
        html,
      });
    },
  },
});

With Resend

import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

export const auth = betterAuth({
  emailVerification: {
    sendVerificationEmail: async ({ user, url }) => {
      await resend.emails.send({
        from: "Your App <noreply@yourapp.com>",
        to: user.email,
        subject: "Verify your email",
        html: `
          <h1>Welcome!</h1>
          <p>Click the link below to verify your email:</p>
          <a href="${url}">Verify Email</a>
          <p>This link expires in 1 hour.</p>
        `,
      });
    },
  },
});

Resend Verification Email

Allow users to request a new verification email:

import { authClient } from "@/lib/auth-client";

async function resendVerification() {
  await authClient.sendVerificationEmail({
    email: "user@example.com",
    callbackURL: "/dashboard",
  });
}

Check Verification Status

const session = await auth.api.getSession({ headers });

if (!session.user.emailVerified) {
  // Redirect to verification page
}

Always use a reputable email service (Resend, SendGrid, AWS SES) in production. Sending from localhost will likely land in spam folders.