Skip to Content
Welcome to the official DBS Documentation! 📚
AdvancedEmail System

Email System

DBS sends transactional emails via the Resend API. All email-sending logic is centralized in src/lib/email.ts.

Configuration

Email settings can be stored two ways:

  1. Environment variablesRESEND_API_KEY, EMAIL_FROM in .env
  2. Database settings — via getSystemConfig(), which falls back to .env if the DB value isn’t set yet
// src/lib/email.ts import { Resend } from 'resend'; import { getSystemConfig } from './config'; import { EmailTemplate } from '@/components/email-template'; export async function sendVerificationEmail({ to, name, verificationUrl, }: { to: string; name: string; verificationUrl: string; }) { const apiKey = await getSystemConfig('RESEND_API_KEY', process.env.RESEND_API_KEY); const from = await getSystemConfig('EMAIL_FROM', process.env.EMAIL_FROM); const resend = new Resend(apiKey); const { error } = await resend.emails.send({ from: from ?? 'noreply@example.com', to, subject: 'Verify your email address', react: EmailTemplate({ type: 'verification', actionUrl: verificationUrl, userName: name, }), }); if (error) { throw new Error(`Failed to send verification email: ${error.message}`); } }

Sending Emails

Import and call the appropriate function:

import { sendVerificationEmail } from '@/lib/email'; // Triggered by Better Auth after registration await sendVerificationEmail({ to: user.email, name: user.name, verificationUrl: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/verify-email?token=${token}`, });

getSystemConfig Pattern

getSystemConfig is the recommended way to read any configuration that might be stored in the database or environment:

import { getSystemConfig } from '@/lib/config'; // Read from DB settings first, fall back to .env const apiKey = await getSystemConfig('RESEND_API_KEY', process.env.RESEND_API_KEY); const fromEmail = await getSystemConfig('EMAIL_FROM', process.env.EMAIL_FROM); const appName = await getSystemConfig('APP_NAME', 'DBS Dashboard');

This allows admins to update configuration keys through the Settings UI without redeploying.

Email Template

The React Email template (src/components/email-template.tsx) supports multiple email types:

// src/components/email-template.tsx import { Html, Body, Container, Heading, Button, Text } from '@react-email/components'; interface EmailTemplateProps { type: 'verification' | 'reset-password' | 'invite' | 'notification'; actionUrl: string; userName?: string; message?: string; } export function EmailTemplate({ type, actionUrl, userName, message }: EmailTemplateProps) { return ( <Html> <Body style={{ fontFamily: 'sans-serif', backgroundColor: '#f4f4f4' }}> <Container style={{ background: '#fff', padding: '24px', borderRadius: '8px' }}> <Heading>DBS — {typeLabels[type]}</Heading> {userName && <Text>Hi {userName},</Text>} <Text>{message ?? typeMessages[type]}</Text> <Button href={actionUrl} style={{ background: '#000', color: '#fff' }}> {typeButtonLabels[type]} </Button> <Text style={{ color: '#888', fontSize: '12px' }}> If you did not request this, you can safely ignore this email. </Text> </Container> </Body> </Html> ); }

Test Email Endpoint

DBS includes a test endpoint to verify your Resend configuration:

POST /api/mail Content-Type: application/json { "to": "test@example.com" }

The POST /api/mail endpoint requires settings.manage permission. Never expose it publicly or use it in automated tests against a real Resend account.

Adding New Email Types

Add the type to EmailTemplate

type: 'verification' | 'reset-password' | 'invite' | 'my-new-type'

Add label, message, and button text

const typeLabels = { // ... 'my-new-type': 'Your Custom Subject', };

Create a sender function in email.ts

export async function sendCustomEmail({ to, name, actionUrl }) { const apiKey = await getSystemConfig('RESEND_API_KEY', process.env.RESEND_API_KEY); const resend = new Resend(apiKey); await resend.emails.send({ from: process.env.EMAIL_FROM!, to, subject: 'Your Custom Email', react: EmailTemplate({ type: 'my-new-type', actionUrl, userName: name }), }); }

Call it from your API route

await sendCustomEmail({ to: user.email, name: user.name, actionUrl });
Last updated on