How to Set Up Transactional Emails (2026)
Transactional emails (welcome, password reset, receipts, notifications) are essential for any app. Here's how to set them up with Resend and React Email.
Step 1: Set Up Resend
npm install resend @react-email/components
Sign up at resend.com and get your API key.
Step 2: Verify Your Domain
Add DNS records to send from your domain (not @resend.dev):
Type: MX Name: send Value: feedback-smtp.resend.com Priority: 10
Type: TXT Name: send Value: v=spf1 include:amazonses.com ~all
Type: TXT Name: resend._domainkey Value: [provided by Resend]
Step 3: Create Email Templates
// emails/welcome.tsx
import { Html, Head, Body, Container, Heading, Text, Button, Hr } from '@react-email/components'
interface WelcomeEmailProps {
name: string
loginUrl: string
}
export function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
return (
<Html>
<Head />
<Body style={{ backgroundColor: '#f6f9fc', fontFamily: '-apple-system, sans-serif' }}>
<Container style={{ maxWidth: '580px', margin: '0 auto', padding: '20px' }}>
<Heading style={{ fontSize: '24px', color: '#1a1a1a' }}>
Welcome to MyApp, {name}! 🎉
</Heading>
<Text style={{ fontSize: '16px', color: '#4a4a4a', lineHeight: '1.5' }}>
Thanks for signing up. You're all set to start using MyApp.
</Text>
<Button
href={loginUrl}
style={{
backgroundColor: '#3b82f6',
color: '#ffffff',
padding: '12px 24px',
borderRadius: '6px',
fontSize: '16px',
textDecoration: 'none',
}}
>
Go to Dashboard
</Button>
<Hr style={{ borderColor: '#e5e5e5', margin: '24px 0' }} />
<Text style={{ fontSize: '12px', color: '#999' }}>
If you didn't create this account, please ignore this email.
</Text>
</Container>
</Body>
</Html>
)
}
Step 4: Send Emails
// lib/email.ts
import { Resend } from 'resend'
import { WelcomeEmail } from '@/emails/welcome'
const resend = new Resend(process.env.RESEND_API_KEY)
export async function sendWelcomeEmail(email: string, name: string) {
await resend.emails.send({
from: 'MyApp <hello@yourapp.com>',
to: email,
subject: `Welcome to MyApp, ${name}!`,
react: <WelcomeEmail name={name} loginUrl="https://yourapp.com/login" />,
})
}
export async function sendPasswordResetEmail(email: string, resetUrl: string) {
await resend.emails.send({
from: 'MyApp <security@yourapp.com>',
to: email,
subject: 'Reset your password',
react: <PasswordResetEmail resetUrl={resetUrl} />,
})
}
Step 5: Trigger from Your App
// Clerk webhook: user.created
export async function POST(req: Request) {
const payload = await req.json()
if (payload.type === 'user.created') {
await sendWelcomeEmail(
payload.data.email_addresses[0].email_address,
payload.data.first_name || 'there',
)
}
return Response.json({ received: true })
}
Common Transactional Emails
| Trigger | Priority | |
|---|---|---|
| Welcome | User signup | High |
| Email verification | Signup / email change | Critical |
| Password reset | Password reset request | Critical |
| Invoice/receipt | Payment processed | High |
| Notification | Various app events | Medium |
Deliverability Tips
- Verify your domain — never send from
@gmail.com - Set up DKIM, SPF, DMARC — Resend handles DKIM/SPF; add DMARC yourself
- Use a subdomain —
send.yourapp.cominstead ofyourapp.com(protects main domain reputation) - Don't mix marketing and transactional — use separate senders
- Include unsubscribe for notifications — required by law for non-critical emails
Preview Emails Locally
npx react-email dev
Opens a local server showing all your email templates with hot reload.
FAQ
Resend vs SendGrid for transactional?
Resend for better DX and React Email. SendGrid for higher volume and more features. For most apps, Resend is the better choice.
Do I need a separate service for marketing emails?
Yes. Use Resend/Postmark for transactional and Loops/ConvertKit for marketing. Different deliverability requirements.
How do I test emails in development?
Use Resend's test mode or send to a personal email. React Email's preview server shows the rendered output without sending.
Bottom Line
Resend + React Email = the fastest path to production transactional emails. Verify your domain, create templates as React components, and trigger sends from webhooks or API routes. The entire setup takes <30 minutes.