Facebook Pixel

Amazon SES Summary and Best Practices Complete Guide for Node.js Email

A comprehensive summary of using Amazon SES with Node.js setup, sending, templates, deliverability, error handling, and best practices.

Amazon SES Summary and Best Practices

This is a complete summary of everything you need to know about sending emails with Amazon SES in your Node.js application.

The Complete SES Setup

1. Verify domain in SES (add DKIM CNAME records)
2. Add SPF and DMARC TXT records
3. Get SMTP credentials (or AWS SDK credentials)
4. Request production access (exit sandbox mode)
5. Install Nodemailer or AWS SDK
6. Create email transport/client
7. Build email templates
8. Send emails (with error handling)
9. Set up bounce/complaint handling (SNS)
10. Monitor deliverability metrics

Best Practices Checklist

Setup

  • Domain verified in SES
  • DKIM records added (3 CNAME)
  • SPF record added (v=spf1 include:amazonses.com ~all)
  • DMARC record added (v=DMARC1; p=quarantine)
  • Production access requested and approved
  • Credentials stored in .env (not in code)

Sending

  • Use consistent from address ([email protected])
  • Include both HTML and plain text versions
  • Use email templates for consistency
  • Send asynchronously (fire-and-forget or queue)
  • Check canSendEmail before sending (skip bounced)
  • Rate limit to stay within SES quotas

Error Handling

  • Try-catch on every email send
  • Retry on throttling (429) with exponential backoff
  • Don't retry on rejections (bad content)
  • Log all email events
  • Store failed emails for later retry
  • Set up SNS bounce/complaint notifications
  • Mark bounced/complained emails in database

Deliverability

  • Warm up domain (start with 50/day)
  • Keep bounce rate < 5%
  • Keep complaint rate < 0.1%
  • No spam trigger words in content
  • Include unsubscribe for notification emails
  • Test with mail-tester.com (aim for 9-10/10)
  • Monitor SES dashboard metrics

Security

  • AWS credentials in .env (never in code)
  • IAM user with minimal SES permissions
  • .env in .gitignore
  • Restrict IAM policy to specific sender email
  • Use IAM roles on EC2 (instead of access keys)

Architecture Summary

User signs up
    ↓
Node.js route handler
    ↓
Queue email (Bull + Redis)
    ↓
Email worker processes job
    ↓
Amazon SES sends email
    ↓
Recipient receives email
    ↓
If bounce/complaint → SNS → Webhook → Update database

Code Summary

// 1. Transport (Nodemailer + SMTP) const transporter = nodemailer.createTransport({ host: process.env.SES_HOST, port: 587, auth: { user: process.env.SES_USER, pass: process.env.SES_PASS } }); // 2. Templates const templates = { welcome: (data) => ({ subject: "...", html: "...", text: "..." }), passwordReset: (data) => ({ subject: "...", html: "...", text: "..." }) }; // 3. Send function with checks const sendSafeEmail = async (user, template, data) => { if (!canSendEmail(user)) return null; try { const t = templates[template](data); return await transporter.sendMail({ from: process.env.SES_FROM, to: user.email, ...t }); } catch (err) { console.error("Email failed:", err); await logEmailFailure(user, template, err); return null; } }; // 4. Queue (Bull) const emailQueue = new Queue("email", { redis: { host: "127.0.0.1", port: 6379 } }); emailQueue.process(async (job) => { const { userId, template, data } = job.data; const user = await User.findById(userId); await sendSafeEmail(user, template, data); }); // 5. Bounce handler (SNS webhook) router.post("/ses/webhook", (req, res) => { const notification = JSON.parse(req.body.Message); if (notification.notificationType === "Bounce") { handleBounce(notification.bounce); } res.status(200).json({ status: "ok" }); });

Environment Variables

# SES SMTP SES_HOST=email-smtp.us-east-1.amazonaws.com SES_PORT=587 SES_USER=AKIAXXXXXXXXX SES_PASS=your-smtp-password [email protected] # Or AWS SDK AWS_ACCESS_KEY_ID=AKIAXXXXXXXXX AWS_SECRET_ACCESS_KEY=your-secret-key AWS_REGION=us-east-1 [email protected] # Redis (for Bull queue) REDIS_HOST=127.0.0.1 REDIS_PORT=6379

Cost Estimation

For DevTinder with 1,000 users sending 5 emails each per month:

Emails: 5,000/month
SES cost: 5,000 / 1,000 × $0.10 = $0.50/month
Free tier (EC2): 62,000/month → $0
Total: $0 (within free tier)

The Takeaway

Amazon SES is a cost-effective ($0.10/1000 emails, free tier 62k/month from EC2), reliable email service for Node.js. The key to success: complete DNS setup (SPF, DKIM, DMARC), use queues for async sending, handle bounces and complaints via SNS, monitor deliverability metrics, and follow email content best practices. For DevTinder, the cost is negligible within the free tier.

Verify domain (add DKIM CNAME records), add SPF and DMARC TXT records, get SMTP or AWS SDK credentials, request production access (exit sandbox), install Nodemailer or AWS SDK, create email transport, build templates, send with error handling, set up SNS bounce/complaint notifications, and monitor deliverability.

Use consistent from address, include HTML and plain text, use templates, send asynchronously via queue, check canSendEmail before sending, retry on throttling with backoff, handle bounces via SNS, warm up domain gradually, keep bounce rate < 5% and complaint rate < 0.1%, and test with mail-tester.com.

$0.10 per 1,000 emails. Free tier includes 62,000 emails/month when sent from EC2. For a small app like DevTinder with 1,000 users sending 5 emails each per month (5,000 total), the cost is $0 (within free tier).

Use the AWS SDK for better performance, SES templates, configuration sets, and detailed errors. Use Nodemailer SMTP if you're using Nodemailer's features, migrating from another SMTP service, or need to switch email providers easily. Both work well.

Set up SNS notifications in SES configuration sets. Create a webhook that receives SNS notifications. For bounces, parse the notification and mark the user as emailBounced in your database. For complaints, mark as emailComplained. Never send to bounced or complained addresses to protect your sender reputation.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.