Email Setup

This guide shows how to configure email sending for PWASK. We use different services for development (testing) and production (real emails).

Quick Setup

Development: Ethereal Email (Recommended)

Ethereal.email is a fake SMTP service perfect for testing emails without sending real ones.

Benefits:

  • 100% free
  • No signup required
  • Instant test accounts
  • Web interface to view sent emails
  • No emails actually sent (perfect for testing)

Setup Steps:

  1. Generate test account (automated):

    # Run this Node.js script once to get credentials
    node -e "require('nodemailer').createTestAccount().then(account => console.log('EMAIL_HOST=smtp.ethereal.email\nEMAIL_PORT=587\nEMAIL_USER=' + account.user + '\nEMAIL_PASS=' + account.pass))"
    
  2. Add to .env.local:

    EMAIL_HOST=smtp.ethereal.email
    EMAIL_PORT=587
    EMAIL_USER=your_generated_user@ethereal.email
    EMAIL_PASS=your_generated_password
    EMAIL_NAME=PWASK Dev
    EMAIL_FROM=noreply@pwask.dev
    EMAIL_TO=test@ethereal.email
    
  3. View sent emails:

Alternative: Manual account creation

  1. Visit https://ethereal.email/create
  2. Click "Create Ethereal Account"
  3. Copy the credentials to your .env.local

Production: Resend (Recommended)

Resend is a modern email API with excellent deliverability and developer experience.

Why Resend:

  • 100 emails/day free forever
  • ✅ 99% deliverability rate
  • ✅ Simple API and SMTP
  • ✅ Custom domain support
  • ✅ Email analytics
  • ✅ Great documentation
  • ✅ No credit card required for free tier

Setup Steps:

  1. Create account:

  2. Verify domain (recommended for production):

    • Go to Domains
    • Add your domain
    • Add DNS records (SPF, DKIM, DMARC)
    • Wait for verification (~5 minutes)
  3. Generate API Key:

    • Go to API Keys
    • Create new API key
    • Copy the key (starts with re_)
  4. Configure for SMTP (easier) or API:

    Option A: SMTP (Recommended - no code changes needed)

    EMAIL_HOST=smtp.resend.com
    EMAIL_PORT=587
    EMAIL_USER=resend
    EMAIL_PASS=re_your_api_key_here
    EMAIL_NAME=PWASK
    EMAIL_FROM=noreply@yourdomain.com  # Must use verified domain
    EMAIL_TO=support@yourdomain.com
    

    Option B: Resend API (requires code changes)

    RESEND_API_KEY=re_your_api_key_here
    EMAIL_FROM=noreply@yourdomain.com
    
  5. Update email route (only if using API):

    // src/app/api/sendmail/route.ts
    import { Resend } from 'resend';
    const resend = new Resend(process.env.RESEND_API_KEY);
    

Alternative Production Services

1. SendGrid (Twilio)

  • Free tier: 100 emails/day forever
  • Pros: Industry standard, reliable
  • Cons: More complex setup, owned by Twilio
  • Website: sendgrid.com

Setup:

EMAIL_HOST=smtp.sendgrid.net
EMAIL_PORT=587
EMAIL_USER=apikey
EMAIL_PASS=SG.your_api_key_here

2. Mailgun

  • Free tier: 5,000 emails/month (first 3 months), then 100 emails/day
  • Pros: Powerful API, good deliverability
  • Cons: Complex pricing after trial
  • Website: mailgun.com

Setup:

EMAIL_HOST=smtp.mailgun.org
EMAIL_PORT=587
EMAIL_USER=postmaster@your-domain.mailgun.org
EMAIL_PASS=your_smtp_password

3. Amazon SES

  • Free tier: 62,000 emails/month (if sending from EC2)
  • Pros: Cheapest for high volume, reliable
  • Cons: Complex setup, requires AWS account
  • Website: aws.amazon.com/ses

4. Brevo (formerly Sendinblue)

  • Free tier: 300 emails/day
  • Pros: Higher free tier, includes SMS
  • Cons: Includes branding in free tier
  • Website: brevo.com

Setup:

EMAIL_HOST=smtp-relay.brevo.com
EMAIL_PORT=587
EMAIL_USER=your_brevo_email
EMAIL_PASS=your_brevo_smtp_key

Environment Variables Reference

# Required for all providers
EMAIL_HOST=smtp.provider.com      # SMTP server hostname
EMAIL_PORT=587                    # SMTP port (usually 587 for TLS)
EMAIL_USER=your_username          # SMTP username
EMAIL_PASS=your_password          # SMTP password or API key
EMAIL_NAME=Your App Name          # Sender display name
EMAIL_FROM=noreply@yourdomain.com # From email address
EMAIL_TO=admin@yourdomain.com     # Default recipient for admin emails

Testing Email Sending

1. Test with Stripe Webhook

After configuring email, test with a Stripe payment:

# Start Stripe CLI listener
stripe listen --forward-to localhost:3000/api/checkout/stripe/webhook

# Trigger a test payment
stripe trigger checkout.session.completed

Check your email service (Ethereal or Resend) to verify the email was sent.

2. Test with API Route Directly

Create a test script:

// scripts/test-email.ts
const response = await fetch('http://localhost:3000/api/sendmail', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    template: 'payment_confirmation',
    to: 'test@example.com',
    email: 'test@example.com',
    name: 'Test User',
    amount: '299 EUR',
    plan: 'lifetime',
    locale: 'en',
  }),
});

console.log('Email sent:', await response.text());

Run with: tsx scripts/test-email.ts

Email Templates

PWASK includes React Email templates in src/emails/:

src/emails/
├── en/
│   ├── payment_confirmation.tsx
│   └── purchase_with_download.tsx
└── fr/
    ├── payment_confirmation.tsx
    └── purchase_with_download.tsx

Available Templates

  1. payment_confirmation.tsx

    • Sent after successful payment
    • Includes payment details and next steps
  2. purchase_with_download.tsx

    • Sent when payment includes a download
    • Includes download link with expiry

Deliverability Best Practices

1. Domain Authentication

Always verify your domain with SPF, DKIM, and DMARC records:

SPF Record (example for Resend):

v=spf1 include:_spf.resend.com ~all

DKIM: Provided by your email service (add to DNS)

DMARC:

v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com

2. From Address

  • Use a verified domain (not @gmail.com in production)
  • Use consistent "from" addresses
  • Example: noreply@yourdomain.com

3. Email Content

  • Include plain text version
  • Avoid spam trigger words
  • Include unsubscribe link (for marketing emails)
  • Keep HTML clean and responsive

4. Monitor Bounce Rates

  • Check your email service dashboard regularly
  • Remove bounced email addresses
  • Monitor spam complaints

Troubleshooting

"Authentication failed"

  • Verify EMAIL_USER and EMAIL_PASS are correct
  • Check if using API key as password (common with Resend, SendGrid)
  • Ensure no extra spaces in environment variables

"Connection timeout"

  • Check EMAIL_HOST and EMAIL_PORT
  • Verify firewall allows outbound SMTP (port 587)
  • Try port 465 (SSL) instead of 587 (TLS)

"Emails not received"

  • Check spam/junk folders
  • Verify domain is authenticated (SPF/DKIM)
  • For Ethereal: check web interface at ethereal.email/messages
  • For production: check email service logs/dashboard

"Invalid sender domain"

  • Verify domain in email service dashboard
  • Wait for DNS propagation (~24 hours)
  • Use verified domain in EMAIL_FROM

Security Notes

  • Never commit .env.local with real credentials
  • Use environment variables in production (Vercel, etc.)
  • Rotate keys if accidentally exposed
  • Keep EMAIL_PASS and API keys server-side only
  • Use separate accounts for dev/staging/production

Recommended: Dev → Production Flow

  1. Local Dev: Use Ethereal (no real emails sent)
  2. Staging: Use Resend sandbox mode or test domain
  3. Production: Use Resend with verified custom domain

This ensures you never accidentally send test emails to real users!

Related Documentation