# Better-Auth Email Verification Setup: The Complete 2026 Guide

_By Tayyab Mughal, Founder & Chief Architect · 06 November 2026 · 4 min read_

> Learn how to configure Better-Auth with SadaSend for sub-150ms transactional email verification, password resets, magic links, and pre-send bounce defense.

A production-ready walkthrough for wiring Better-Auth email verification, password resets, and magic links with SadaSend and React Email in Next.js 15 and Bun.

## Why Better-Auth is dominating TypeScript authentication in 2026

Better-Auth has rapidly emerged as the primary authentication library for modern TypeScript stacks. Unlike legacy authentication libraries that tightly couple to monolithic database ORMs or enforce complex multi-file configurations, Better-Auth is lightweight, framework-agnostic, and built with first-class plugin support.

However, an authentication library only handles session state and token generation. The critical moment in user onboarding — delivering the verification link or 6-digit one-time password (OTP) — depends entirely on your transactional email infrastructure. If verification emails take 45 seconds to arrive or get flagged as spam by Google and Microsoft, users abandon signup.

By pairing Better-Auth with SadaSend, you get sub-150ms ingestion latency, native Dual-DKIM signing (RSA-2048 + Ed25519), and an in-flight bounce shield that detects dead or misspelled mailboxes before they pollute your user database.

| Auth Feature | Better-Auth Mechanism | SadaSend Delivery Advantage |
| --- | --- | --- |
| Email Verification | requireEmailVerification: true | Sub-150ms direct MX dispatch with zero waiting in queue |
| Password Resets | sendResetPassword hook | Authenticated TLS submission on dedicated EU infrastructure |
| Magic Link Login | magicLink plugin | In-flight link scanning ensures clean spam reputation |
| Two-Factor OTP | twoFactor / emailOTP plugin | Instant delivery before the 5-minute code window expires |

## 1. Installing dependencies & configuring the SadaSend client

First, install Better-Auth and the official SadaSend TypeScript SDK in your project:

```bash
npm install better-auth sadasend
```

Next, create your centralized authentication configuration in lib/auth.ts. We initialize the SadaSend client using your scoped API key:

## 2. Wiring sendVerificationEmail & sendResetPassword in auth.ts

Better-Auth provides clean async callbacks for outbound transactional emails. Here is the complete production configuration with pre-send bounce defense enabled:

```typescript
import { betterAuth } from 'better-auth';
import { SadaSend } from 'sadasend';

// Initialize SadaSend with scoped API credentials
const sadasend = new SadaSend({
  apiKey: process.env.SADASEND_API_KEY!,
});

export const auth = betterAuth({
  emailAndPassword: {
    enabled: true,
    requireEmailVerification: true,
    sendVerificationEmail: async ({ user, url }) => {
      // Dispatch verification link with in-flight bounce defense
      const response = await sadasend.emails.send({
        from: 'security@yourdomain.com',
        to: user.email,
        subject: 'Verify your email address',
        html: `
          <div style="font-family: sans-serif; max-width: 560px; margin: 0 auto;">
            <h2>Verify your account</h2>
            <p>Hi ${user.name || 'there'},</p>
            <p>Click the link below to verify your email and activate your account:</p>
            <p><a href="${url}" style="display: inline-block; padding: 12px 24px; background: #000; color: #fff; text-decoration: none; border-radius: 6px;">Verify Email</a></p>
            <p style="color: #666; font-size: 13px;">If you did not request this, please ignore this email.</p>
          </div>
        `,
        verifyBeforeSend: true, // Blocks invalid syntax & dead MX domains
      });

      console.log('Verification dispatched:', response.id);
    },
    sendResetPassword: async ({ user, url }) => {
      await sadasend.emails.send({
        from: 'security@yourdomain.com',
        to: user.email,
        subject: 'Reset your password',
        html: `
          <div style="font-family: sans-serif; max-width: 560px; margin: 0 auto;">
            <h2>Password Reset Request</h2>
            <p>Click below to reset your password. This link expires in 15 minutes:</p>
            <p><a href="${url}" style="display: inline-block; padding: 12px 24px; background: #000; color: #fff; text-decoration: none; border-radius: 6px;">Reset Password</a></p>
          </div>
        `,
      });
    },
  },
});
```

## 3. Supporting Email OTP and 2FA with Better-Auth plugins

If your application relies on 6-digit numeric OTP verification codes rather than clickable magic links, Better-Auth’s emailOTP plugin connects seamlessly using the same SadaSend client:

```typescript
import { emailOTP } from 'better-auth/plugins';

export const auth = betterAuth({
  plugins: [
    emailOTP({
      async sendVerificationOTP({ email, otp, type }) {
        await sadasend.emails.send({
          from: 'auth@yourdomain.com',
          to: email,
          subject: `Your ${type === 'sign-in' ? 'Login' : 'Verification'} Code: ${otp}`,
          html: `
            <div style="font-family: sans-serif; text-align: center; padding: 24px;">
              <h2>Your Verification Code</h2>
              <p style="font-size: 32px; font-weight: bold; letter-spacing: 4px; color: #111;">${otp}</p>
              <p style="color: #666;">This code is valid for 5 minutes. Do not share it with anyone.</p>
            </div>
          `,
          tags: ['auth-otp', type],
        });
      },
    }),
  ],
});
```

## 4. Testing auth flows in CI/CD without polluting real inboxes

In automated test suites (e.g. Playwright or Cypress), testing Better-Auth email verification usually requires fragile third-party mail tools. SadaSend includes native ephemeral test inboxes with real-time Server-Sent Events push streams, allowing your CI pipeline to extract the verification link and click it in under 150ms without waiting for polling loops.

---

_Tags: Better-Auth, Authentication, TypeScript, Next.js 15, Transactional Email_
