Wraps Logo
Engineering10 min readWraps Team

AWS SES Setup Simplified:From Hours to Minutes

If you've ever tried to set up AWS SES from scratch, you know the pain. What should be a simple “send email from my app” turns into a multi-day odyssey through IAM policies, sandbox approvals, DKIM configuration, and prayers to the DNS propagation gods.

We built Wraps because this experience is broken—and because you shouldn't have to choose between AWS economics and developer sanity.

Minutes to deploy
$0.10 per 1K emails
Your AWS, your data

The Problem: SES Setup is a Nightmare

Developer forums are filled with horror stories about AWS SES setup. The process involves navigating the AWS console, writing IAM policies by hand, configuring DKIM records, setting up event tracking pipelines, and managing credentials—all before you can send a single email.

I have been denied production access about 3 times now... It's frustrating as the responses we get from the AWS Trust & Safety Team are very point blank and appear to be canned messages for rejecting.
AWS re:Post
After a whole day of configurations in the AWS console I still couldn't send one single email. When going back to Resend, I managed to send my first email in literally 1 minute.SES: 15 hours = $1500; Resend: 15mn = $25
Nino Filiu, Dev.to

The time investment is brutal. When you factor in engineer time, the cost of manual SES setup can dwarf the savings you get from AWS's low per-email pricing. Developers routinely spend full days just getting to the point where they can send a single test email.

But here's the thing—once SES is set up, it's incredibly cheap ($0.10 per 1,000 emails) and you own the infrastructure. The problem isn't SES itself. It's the setup.

The Solution: Infrastructure as Code, Zero Console

Wraps deploys production-ready email infrastructure to your AWS account using Pulumi under the hood. One command. No AWS console spelunking. No sandbox approval essays.

terminal

That's it. In about 2 minutes, you have:

  • SES configured with your domain
  • DKIM, SPF, and DMARC ready for DNS
  • Event tracking via EventBridge
  • Email history in DynamoDB
  • Lambda functions processing delivery events
  • Proper IAM roles with least-privilege access
  • OIDC authentication (no stored credentials)
~2min
Setup Time
vs 4-8 hours
0
AWS Resources
auto-configured
Zero
Credentials
stored secrets
$0.0
Cost
per 1K emails

See It In Action

Terminal
$npx @wraps.dev/cli email init
◐ Validating AWS credentials...

Option 1: The CLI Path (Fastest)

Installation

Install the CLI globally or run it directly with npx:

terminal
npm install -g @wraps.dev/cli
# or just use npx
npx @wraps.dev/cli email init

Requirements

  • Node.js 20+
  • AWS CLI configured with valid credentials
  • An AWS account with appropriate permissions

Deploying Infrastructure

Run the init command and the CLI walks you through the entire process:

terminal
wraps email init

The CLI handles five steps automatically:

  1. Credential validation – Confirms your AWS access
  2. Preset selection – Choose Starter, Production, or Enterprise
  3. Cost estimation – Shows estimated monthly AWS costs
  4. Deployment – Pulumi provisions everything
  5. OIDC setup – Configures credential-free access for Vercel

Command Options

terminal
wraps email init -p vercel -r us-east-1 -y
FlagDescription
-p, --providerHosting provider (vercel, aws, railway, other)
-r, --regionAWS region
-y, --yesSkip confirmation prompts

Adding Your Domain

Once infrastructure is deployed, add your sending domain. This creates the SES identity and returns DKIM tokens for DNS configuration.

terminal
wraps email domains add -d yourdomain.com

Verifying DNS Configuration

After adding DNS records, verify that everything is configured correctly. The CLI checks DKIM CNAME records, SPF TXT record, DMARC TXT record, and MAIL FROM MX records (if configured).

terminal
wraps email domains verify -d yourdomain.com

Managing Your Deployment

The CLI provides commands for every lifecycle stage of your email infrastructure:

terminal
# Check status of your infrastructure
wraps email status

# List all domains
wraps email domains list

# Upgrade to a higher tier
wraps email upgrade

# Remove everything (careful!)
wraps email destroy

Manual vs Wraps

TaskManual SESWith Wraps
Time to first email4-8 hours
~2 minutes
DNS configurationManual lookup
Auto-generated
IAM policiesWrite from scratch
Least-privilege included
Event trackingBuild pipeline
One command
Credential managementStore secrets
OIDC (zero secrets)

Option 2: Understanding the IaC (What Gets Deployed)

Under the hood, Wraps uses Pulumi with @pulumi/aws to provision infrastructure. All resources are namespaced with wraps-email-* for easy identification. Here's the complete picture.

IAM Resources

ResourcePurpose
wraps-email-roleMain IAM role for SDK access
wraps-email-policyLeast-privilege policy for email operations
OIDC ProviderEnables Vercel to assume the role without stored credentials

SES Resources

ResourcePurpose
wraps-email-config-setConfiguration set for event tracking
Email IdentitiesYour verified domains

Event Tracking Architecture

Every email event flows through a reliable, serverless pipeline. SES emits events to EventBridge, which routes them to SQS for buffered processing. A Lambda function reads from the queue and writes structured records to DynamoDB. Failed events land in a Dead Letter Queue for debugging.

Event Processing Architecture

SES
EventBridge
SQS
Lambda
DynamoDB

Email sent through SES triggers delivery events

ResourcePurpose
EventBridge RuleCaptures SES events (send, delivery, open, click, bounce, complaint)
SQS QueueBuffers events for reliable processing
SQS Dead Letter QueueStores failed events for debugging
Lambda FunctionProcesses events and writes to DynamoDB

Storage

ResourcePurpose
wraps-email-historyDynamoDB table for email history
wraps-email-eventsDynamoDB table for delivery events

Event Types Tracked

SENDDELIVERYOPENCLICKBOUNCECOMPLAINTREJECTRENDERING_FAILUREDELIVERY_DELAYSUBSCRIPTION

Resource Naming Convention

All Wraps resources follow the pattern wraps-email-{resource-type}. Every resource is tagged with ManagedBy: 'wraps-cli' so you can easily identify and audit Wraps-managed infrastructure in your AWS account.

Configuration Presets

Choose your deployment complexity based on your needs. Upgrade anytime with wraps email upgrade.

Sending Emails with the SDK

Once infrastructure is deployed, install the TypeScript SDK and start sending. The SDK is fully typed and handles credential resolution automatically.

terminal
npm install @wraps.dev/email

On Vercel, credentials are automatic via OIDC—no environment variables, no stored secrets. The SDK detects the runtime environment and acquires temporary AWS credentials transparently.

import { Wraps } from '@wraps.dev/email';

const wraps = new Wraps();

await wraps.emails.send({
  from: 'hello@yourdomain.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: '<h1>Hello from Wraps!</h1>',
});

Vercel OIDC Integration

One of the nastier parts of AWS integrations is credential management. Wraps eliminates this entirely using OIDC federation.

How It Works

OIDC Flow
Vercel → OIDC Token → AWS STS → Temporary Credentials → SES
  1. Your Vercel deployment requests an OIDC token
  2. AWS STS validates the token and issues temporary credentials
  3. The SDK uses those credentials to call SES
  4. Credentials rotate automatically—nothing stored

Setup

During wraps email init, you'll be asked for your Vercel team slug and project name. These configure the OIDC trust relationship so your deployments can assume the IAM role without any stored secrets. See our Next.js + Vercel + SES guide for a complete walkthrough.

Connecting Existing SES

Already have SES configured? Wraps can layer on top without touching your existing setup:

terminal
wraps email connect

This command scans your existing AWS resources (SES domains, config sets), prompts for which features you want to add, and deploys Wraps resources non-destructively. It never modifies your existing configuration—all new resources are created with the wraps-email- prefix.

Troubleshooting

“AWS credentials not found”

Ensure the AWS CLI is configured by running aws configure. Verify your identity with aws sts get-caller-identity.

“Insufficient permissions”

Your AWS user needs permissions to create IAM roles, SES identities, DynamoDB tables, Lambda functions, SQS queues, and EventBridge rules. Use an admin user for initial setup.

“Domain verification pending”

Add the DKIM CNAME records to your DNS provider. Run wraps email domains verify -d yourdomain.com to check progress. DNS propagation can take up to 72 hours, though it usually completes in minutes. Need help with sandbox approval? See our SES sandbox escape guide.

“OIDC provider already exists”

The Vercel OIDC provider may exist from another project. The CLI handles this gracefully and reuses existing providers—no action needed on your part.

What You're Not Paying For

Traditional email APIs charge you per email sent, plus platform fees, plus storage fees. With Wraps, the model is different:

  • You pay AWS directly for sending ($0.10 per 1,000 emails)
  • Your data stays in your AWS account
  • No vendor lock-in—your infrastructure keeps working even if you stop using Wraps

If you're sending 100,000 emails per month: Resend ~$90/month vs Wraps ~$12 to AWS.

Design Principles

Every CLI decision follows these principles:

Non-Destructive

We never modify your existing AWS resources

Namespaced

All resources prefixed with wraps-email- for easy identification

Fail Fast

Validate early, so you know immediately if something’s wrong

Great UX

Clear output, helpful error messages, suggestions for next steps

Zero Credentials Stored

OIDC authentication only

Continue Learning

Ready to escape the AWS console?

You'll have production email infrastructure in your AWS account in minutes.

npx @wraps.dev/cli email init
Explore the CLIRead the Docs