Skip to main content
Cap uses email for passwordless authentication. Without email configured, login links appear in server logs. This guide shows how to set up email delivery using Resend.

Why Email Configuration Matters

Without email:
  • Users must access server logs to get login links
  • No password reset emails
  • No notification emails
  • Poor user experience
With email:
  • One-click login from inbox
  • Professional user experience
  • Notification support
  • Production-ready authentication
Resend is Cap’s officially supported email provider.

Why Resend?

  • Simple API and setup
  • Generous free tier (3,000 emails/month)
  • Excellent deliverability
  • Built for developers
  • No credit card required for trial

Setup Steps

1

Create Resend Account

  1. Go to resend.com
  2. Click Sign Up
  3. Verify your email address
  4. Complete onboarding
2

Add and Verify Domain

  1. Go to Domains in Resend dashboard
  2. Click Add Domain
  3. Enter your domain (e.g., yourdomain.com)
  4. Add the DNS records shown:
Required DNS Records:
Type: TXT
Name: @
Value: resend-verification=xxxxx

Type: MX
Name: @
Priority: 10
Value: feedback-smtp.us-east-1.amazonses.com

Type: TXT
Name: @
Value: v=spf1 include:amazonses.com ~all

Type: TXT
Name: resend._domainkey
Value: p=MIGfMA0GCSqGSIb3DQEBA...
DNS changes can take up to 48 hours to propagate, but usually complete within minutes.
3

Verify Domain

  1. After adding DNS records, click Verify in Resend
  2. Wait for verification to complete
  3. Status should show Verified
  • Wait 5-10 minutes and try again
  • Use DNS checker to verify records propagated
  • Ensure records match exactly (no extra quotes or spaces)
  • Check with your DNS provider’s support
4

Create API Key

  1. Go to API Keys
  2. Click Create API Key
  3. Configure:
    • Name: Cap Production
    • Permission: Full Access (or Sending Access)
    • Domain: Select your verified domain
  4. Copy the API key (starts with re_)
Save the API key immediately. Resend only shows it once.
5

Configure Cap

Add these environment variables to your .env file:
.env
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxx
RESEND_FROM_DOMAIN=yourdomain.com
The from address will be: [email protected]
6

Restart Cap

Apply the new configuration:
docker compose down
docker compose up -d
7

Test Email

  1. Go to your Cap instance
  2. Click Sign In
  3. Enter your email address
  4. Check your inbox for the login email
If you don’t receive the email:
  • Check spam folder
  • Verify domain is verified in Resend
  • Check Cap logs for errors: docker compose logs cap-web

Using a Subdomain

If you can’t add DNS records to your main domain, use a subdomain:
1

Create Subdomain

Create a subdomain like mail.yourdomain.com
2

Add to Resend

Add mail.yourdomain.com as a domain in Resend
3

Configure Cap

.env
RESEND_FROM_DOMAIN=mail.yourdomain.com
Emails will be sent from: [email protected]

Custom From Address

Change the sender name and email:
This requires code modification. Cap currently uses noreply@ as the sender.
To customize:
  1. Fork the Cap repository
  2. Edit apps/web/app/api/auth/[...nextauth]/route.ts
  3. Find the Resend email configuration
  4. Change from field:
    from: `Cap <support@${process.env.RESEND_FROM_DOMAIN}>`
    
  5. Rebuild and deploy

Email Template Customization

Cap uses default NextAuth email templates. To customize:
  1. Create custom email templates
  2. Modify the NextAuth configuration in apps/web/app/api/auth/[...nextauth]/route.ts
  3. Add custom HTML/text templates
See NextAuth.js Email Provider docs for details.

Alternative Email Providers

While Resend is recommended, Cap can work with other providers using SMTP.

Using SMTP

SMTP support requires code modification. Cap’s current codebase is designed for Resend’s API.
To use SMTP providers (SendGrid, Mailgun, Postmark, etc.):
  1. Modify NextAuth configuration to use SMTP
  2. Update apps/web/app/api/auth/[...nextauth]/route.ts:
    import { EmailProvider } from "next-auth/providers/email";
    
    providers: [
      EmailProvider({
        server: {
          host: process.env.SMTP_HOST,
          port: Number(process.env.SMTP_PORT),
          auth: {
            user: process.env.SMTP_USER,
            pass: process.env.SMTP_PASSWORD,
          },
        },
        from: process.env.EMAIL_FROM,
      }),
    ]
    
  3. Add environment variables:
    .env
    SMTP_HOST=smtp.sendgrid.net
    SMTP_PORT=587
    SMTP_USER=apikey
    SMTP_PASSWORD=SG.xxxxxxxxx
    EMAIL_FROM=[email protected]
    

Monitoring Email Delivery

Resend Dashboard

  1. Go to Resend Dashboard
  2. View all sent emails
  3. Check delivery status:
    • Delivered - Successfully delivered
    • Bounced - Invalid email address
    • Complained - Marked as spam
    • Queued - Being processed

Cap Logs

Check Cap logs for email sending:
docker compose logs cap-web | grep -i email
Successful email:
Email sent to [email protected] via Resend
Failed email:
Error sending email: Invalid API key

Troubleshooting

No Email Received

Login emails might be filtered as spam initially. Mark as “Not Spam” to improve deliverability.
  1. Go to Resend dashboard
  2. Check domain status is Verified
  3. Re-verify if needed
docker compose logs cap-web | grep -i "resend\|email"
Look for authentication errors.
Test API key directly:
curl -X POST 'https://api.resend.com/emails' \
  -H 'Authorization: Bearer re_xxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "[email protected]",
    "to": "[email protected]",
    "subject": "Test Email",
    "html": "<p>Test email from Resend</p>"
  }'
Successful response:
{"id":"49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"}

Emails Go to Spam

1

Verify SPF, DKIM, DMARC

Ensure all DNS records are properly configured:
  • SPF: Authorizes Resend to send from your domain
  • DKIM: Cryptographic signature for authenticity
  • DMARC: Policy for handling failed authentication
Check with MXToolbox
2

Warm Up Domain

New domains have poor reputation. Gradually increase sending volume:
  • Day 1: 10-20 emails
  • Day 2: 50 emails
  • Week 1: 100/day
  • Week 2: 500/day
  • After month: Full volume
3

Monitor Bounce Rate

Keep bounce rate below 5%:
  • Remove invalid email addresses
  • Use double opt-in for signups
  • Monitor Resend dashboard for bounces
4

Improve Content

  • Avoid spam trigger words
  • Include unsubscribe link (for newsletters)
  • Use plain text + HTML version
  • Proper from name and email

Rate Limiting

Resend free tier limits:
  • 3,000 emails/month
  • 100 emails/day (first month)
If you hit limits:
  1. Check Resend dashboard for current usage
  2. Upgrade to paid plan ($20/month for 50,000 emails)
  3. Or implement email queue to spread sends

Invalid API Key Error

Error: Invalid API key
Fix:
  1. Verify RESEND_API_KEY in .env is correct
  2. Key should start with re_
  3. Ensure no extra spaces or quotes
  4. Create new API key if needed
  5. Restart Cap after changing

Production Best Practices

Security

  • Never commit API keys to git
  • Use environment variables only
  • Rotate API keys periodically
  • Use separate keys for staging/production
  • Enable 2FA on Resend account

Deliverability

  • Always verify your domain
  • Configure all DNS records (SPF, DKIM, DMARC)
  • Monitor bounce and complaint rates
  • Keep email list clean
  • Use descriptive from names
  • Include physical address in footer (legal requirement in some regions)

Monitoring

  • Set up Resend webhooks for delivery events
  • Monitor email sending in logs
  • Track bounce and complaint rates
  • Set up alerts for failed sends
  • Review Resend analytics monthly

Webhooks (Advanced)

Receive real-time delivery notifications:
1

Create Webhook Endpoint

Add to your Cap deployment (requires code modification):
// app/api/webhooks/resend/route.ts
export async function POST(req: Request) {
  const event = await req.json();

  switch (event.type) {
    case 'email.delivered':
      console.log('Email delivered:', event.data.email_id);
      break;
    case 'email.bounced':
      console.log('Email bounced:', event.data.email_id);
      break;
  }

  return new Response('OK', { status: 200 });
}
2

Configure in Resend

  1. Go to Webhooks in Resend
  2. Click Add Webhook
  3. URL: https://cap.yourdomain.com/api/webhooks/resend
  4. Select events: delivered, bounced, complained

Cost Estimation

Resend Pricing:
TierPriceEmails/monthBest For
Free$03,000Testing, small teams
Pro$2050,000Small businesses
Business$80250,000Growing companies
EnterpriseCustomCustomLarge deployments
Calculating your needs:
  • Login emails: ~1-3 per user per month
  • 100 users = ~300 emails/month
  • 1,000 users = ~3,000 emails/month (Free tier)
  • 10,000 users = ~30,000 emails/month (Pro tier)

Next Steps

Environment Variables

Complete email configuration reference

SSL/HTTPS

Secure your deployment

Troubleshooting

Debug email issues

Scaling

Scale email for production

Build docs developers (and LLMs) love