How to Set Up Email Sending for Your SaaS (2026)
Your SaaS needs email: welcome messages, password resets, receipts, notifications, and eventually marketing. Here's how to set it up properly — DNS, deliverability, templates, and the right tools.
The Two Types of Email
Transactional Email
Triggered by user actions: welcome emails, password resets, receipts, notifications. Must be fast and reliable. Users expect these immediately.
Marketing Email
Newsletters, product updates, promotions. Sent in bulk. Needs unsubscribe links and CAN-SPAM compliance.
Use different services for each. Transactional: Resend or Postmark. Marketing: Loops, beehiiv, or ConvertKit.
Step 1: Choose a Transactional Email Provider
| Provider | Free Tier | Pricing | Best For |
|---|---|---|---|
| Resend | 3,000/mo | $20/mo (50K) | Developer DX |
| Postmark | 100/mo | $15/mo (10K) | Deliverability |
| SendGrid | 100/day | $20/mo (50K) | Scale |
| AWS SES | 62K/mo (from EC2) | $0.10/1K | Budget at scale |
Recommendation: Resend for most SaaS apps. Best DX, React Email support, generous free tier.
Step 2: DNS Setup (Critical for Deliverability)
SPF Record
Tells email servers which services can send on your behalf:
Type: TXT
Name: @
Value: v=spf1 include:resend.com ~all
DKIM Record
Cryptographic signature proving emails are from you. Your email provider gives you a DKIM record to add:
Type: CNAME
Name: resend._domainkey
Value: (provided by Resend)
DMARC Record
Policy for handling failed SPF/DKIM checks:
Type: TXT
Name: _dmarc
Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
Why DNS Matters
Without proper DNS records, your emails land in spam. Gmail, Outlook, and Yahoo require SPF, DKIM, and DMARC in 2026. This isn't optional.
Step 3: Set Up Resend
npm install resend
// src/lib/email.ts
import { Resend } from 'resend'
export const resend = new Resend(process.env.RESEND_API_KEY)
export async function sendEmail({
to,
subject,
html,
}: {
to: string
subject: string
html: string
}) {
const { data, error } = await resend.emails.send({
from: 'YourApp <hello@yourdomain.com>',
to,
subject,
html,
})
if (error) {
console.error('Email send failed:', error)
throw error
}
return data
}
Step 4: Email Templates with React Email
Build emails with React components instead of raw HTML:
npm install @react-email/components
// src/emails/welcome.tsx
import { Html, Head, Body, Container, Text, Button, Hr } from '@react-email/components'
export function WelcomeEmail({ name, loginUrl }: { name: string; loginUrl: string }) {
return (
<Html>
<Head />
<Body style={{ fontFamily: 'sans-serif', backgroundColor: '#f4f4f5' }}>
<Container style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
<Text style={{ fontSize: '24px', fontWeight: 'bold' }}>
Welcome to YourApp, {name}! 🎉
</Text>
<Text>
Your account is ready. Here's what to do next:
</Text>
<Text>1. Create your first project</Text>
<Text>2. Invite your team</Text>
<Text>3. Start building</Text>
<Hr />
<Button
href={loginUrl}
style={{
backgroundColor: '#000',
color: '#fff',
padding: '12px 24px',
borderRadius: '6px',
textDecoration: 'none',
}}
>
Go to Dashboard
</Button>
</Container>
</Body>
</Html>
)
}
Send with React Email + Resend
import { WelcomeEmail } from '@/emails/welcome'
import { render } from '@react-email/render'
await resend.emails.send({
from: 'YourApp <hello@yourdomain.com>',
to: user.email,
subject: 'Welcome to YourApp!',
react: <WelcomeEmail name={user.name} loginUrl="https://yourapp.com/dashboard" />,
})
Step 5: Essential Email Flows
1. Welcome Email (on signup)
Trigger: User creates account Content: Welcome message, getting started steps, CTA to dashboard
2. Email Verification
Trigger: User signs up (if not using Clerk/Auth0 which handle this) Content: Verification link
3. Password Reset
Trigger: User requests reset Content: Reset link (expires in 1 hour)
4. Payment Receipt
Trigger: Stripe webhook (invoice.payment_succeeded) Content: Amount, plan, next billing date, invoice PDF link
5. Usage Alert
Trigger: User approaches plan limit Content: Current usage, limit, upgrade CTA
6. Trial Ending
Trigger: 3 days before trial expires Content: Trial end date, what they'll lose, upgrade CTA
Deliverability Checklist
- SPF record configured
- DKIM record configured
- DMARC record configured
- Sending from a custom domain (not @gmail.com)
- Reply-to address is monitored
- Unsubscribe link in marketing emails
- Physical address in marketing emails (CAN-SPAM)
- Bounce handling configured
- Not sending to purchased email lists (ever)
- Warming up new domain (start low volume, increase gradually)
Domain Warming
New domains have no email reputation. ISPs are suspicious of unknown senders. Warm up gradually:
- Week 1: 50-100 emails/day (transactional only)
- Week 2: 200-500 emails/day
- Week 3: 500-1,000 emails/day
- Week 4+: Normal volume
Don't blast 10,000 marketing emails from a new domain on day one. You'll end up in spam.
FAQ
Can I use Gmail/Outlook to send transactional email?
No. Gmail limits you to 500 emails/day and doesn't support custom domains properly. Use a dedicated service.
How do I avoid the spam folder?
DNS records (SPF, DKIM, DMARC), custom domain, warm up gradually, don't use spam trigger words, include an unsubscribe link, and send emails people actually want.
Should I use the same service for transactional and marketing?
No. Use Resend/Postmark for transactional (fast, reliable). Use Loops/beehiiv for marketing (list management, analytics). This protects your transactional deliverability.
How much does email cost at scale?
With Resend: 50K emails/month = $20. With AWS SES: 100K emails/month = $10. Email is cheap.
Bottom Line
Set up DNS records (SPF, DKIM, DMARC) on day one. Use Resend + React Email for beautiful transactional emails. Keep transactional and marketing email separate. Warm up your domain gradually. Total setup time: 2-3 hours for a production-ready email system.