Engineering Originally on dev.to

AWS SES Setup Guide for Startups: Domain Verification, DKIM, SPF, DMARC in 30 Minutes

The exact steps to go from zero to sending verified emails with AWS SES and proper authentication in 30 minutes.

P
Pablo Inigo · Founder & Engineer
2 min read
Email envelope with SPF, DKIM, and DMARC authentication checkmarks

Setting up transactional email shouldn’t take a week. Here’s the exact steps to go from zero to sending verified emails with AWS SES, with proper DKIM/SPF/DMARC — in 30 minutes.

The Goal

Send [email protected] emails that land in inbox (not spam), with full authentication.

Step 1: Verify Your Domain (5 min)

aws ses verify-domain-identity --domain yourdomain.com --region eu-central-1

This returns a TXT record to add to your DNS. Add it, wait for verification.

Step 2: DKIM (5 min)

aws ses verify-domain-dkim --domain yourdomain.com --region eu-central-1

Returns 3 CNAME records. Add all three to DNS:

[token1]._domainkey.yourdomain.com → [token1].dkim.amazonses.com
[token2]._domainkey.yourdomain.com → [token2].dkim.amazonses.com
[token3]._domainkey.yourdomain.com → [token3].dkim.amazonses.com

Step 3: SPF + DMARC (5 min)

Add these DNS records:

# SPF - allows SES to send on your behalf
TXT  yourdomain.com  "v=spf1 include:amazonses.com ~all"

# DMARC - tells receivers to trust SPF/DKIM
TXT  _dmarc.yourdomain.com  "v=DMARC1; p=none;"

# Custom MAIL FROM (optional but recommended)
MX   mail.yourdomain.com  feedback-smtp.eu-central-1.amazonses.com
TXT  mail.yourdomain.com  "v=spf1 include:amazonses.com ~all"

Important: Only ONE DMARC record. Duplicate DMARC records = both get ignored = emails go to spam.

Step 4: Request Production Access (10 min)

SES starts in sandbox mode (can only send to verified emails). Request production access through the AWS Console → SES → Account Dashboard → Request Production Access.

Step 5: Send From Node.js

import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';

const ses = new SESClient({ region: 'eu-central-1' });

await ses.send(new SendEmailCommand({
  Source: '[email protected]',
  Destination: { ToAddresses: [userEmail] },
  Message: {
    Subject: { Data: 'Welcome!' },
    Body: { Html: { Data: htmlContent } }
  }
}));

The Gotcha: Region Matters

SES is regional. If you verify in eu-central-1, you must send from eu-central-1. Sending from eu-west-1 with credentials from eu-central-1 will fail silently.

// CRITICAL: Must match the region where you verified
const ses = new SESClient({ region: 'eu-central-1' });

Cost

At startup volumes (< 1,000 emails/month): under $1/month.

This setup powers email notifications at MisuJob — job match alerts, application confirmations, and password resets.


What email service do you use? SES, SendGrid, Postmark? What’s your experience?

AWS Email DevOps Startup
Share
P
Pablo Inigo

Founder & Engineer

Building MisuJob — an AI-powered job matching platform processing 1M+ tech job listings daily.

Engineering updates

Technical deep dives delivered to your inbox.

Find your next role with AI

Upload your CV. Get matched to 50,000+ jobs. Auto-apply to the best fits.

Get Started Free

User

Dashboard Profile Subscription