SES
Amazon Simple Email Service v2 for sending transactional and marketing emails.
Configuration
| Property | Value |
|---|---|
| Protocol | RestJson1 |
| Signing Name | ses |
| API Version | v2 |
| Persistence | No |
SES v2 uses REST-style routing with JSON bodies. All paths are under /v2/email/....
Quick Start
Verify a sender identity and send an email:
# Create (verify) a sender identity
curl -s -X POST http://localhost:4566/v2/email/identities \
-H "Content-Type: application/json" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/ses/aws4_request, SignedHeaders=host, Signature=fake" \
-d '{"EmailIdentity":"[email protected]","Tags":[]}'
# Send an email
curl -s -X POST http://localhost:4566/v2/email/outbound-emails \
-H "Content-Type: application/json" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/ses/aws4_request, SignedHeaders=host, Signature=fake" \
-d '{
"FromEmailAddress": "[email protected]",
"Destination": {"ToAddresses": ["[email protected]"], "CcAddresses": [], "BccAddresses": []},
"Content": {
"Simple": {
"Subject": {"Data": "Hello from AWSim!"},
"Body": {
"Text": {"Data": "This is a plain text email."},
"Html": {"Data": "<h1>Hello!</h1><p>This is an HTML email.</p>"}
}
}
}
}'Operations
Emails
SendEmail— send an email to one or more recipients- Path:
POST /v2/email/outbound-emails - Input:
FromEmailAddress(required, must be a verified identity)Destination:{ToAddresses, CcAddresses, BccAddresses}(lists of email addresses)Content: one of:Simple:{Subject: {Data}, Body: {Text: {Data}, Html: {Data}}}Template:{TemplateName, TemplateData}(JSON string with substitution variables)Raw:{Data}(base64-encoded raw MIME message)
- Optional:
ReplyToAddresses,FeedbackForwardingEmailAddress,EmailTags(list of{Name, Value})
- Returns:
MessageId
- Path:
Identities
CreateEmailIdentity— register a domain or email address as a verified sender identity- Path:
POST /v2/email/identities - Input:
EmailIdentity(email address or domain name), optionalTags - Returns:
IdentityType(EMAIL_ADDRESSorDOMAIN),VerifiedForSendingStatus(truein AWSim),DkimAttributes
- Path:
GetEmailIdentity— get details of a verified identity- Path:
GET /v2/email/identities/{EmailIdentity} - Returns:
IdentityType,VerifiedForSendingStatus,DkimAttributes,Tags
- Path:
ListEmailIdentities— list all verified sender identities- Path:
GET /v2/email/identities - Returns: paginated
EmailIdentitieslist withIdentityName,IdentityType,SendingEnabled
- Path:
DeleteEmailIdentity— remove a verified identity- Path:
DELETE /v2/email/identities/{EmailIdentity}
- Path:
Templates
CreateEmailTemplate— create a reusable email template with variable substitution- Path:
POST /v2/email/templates - Input:
TemplateName,TemplateContentwithSubject,Text,Html(usefor substitutions)
- Path:
GetEmailTemplate— get a template by name- Path:
GET /v2/email/templates/{TemplateName}
- Path:
ListEmailTemplates— list all email templates- Path:
GET /v2/email/templates
- Path:
DeleteEmailTemplate— delete a template- Path:
DELETE /v2/email/templates/{TemplateName}
- Path:
Account
GetAccount— get account-level sending details and limits- Path:
GET /v2/email/account - Returns:
SendingEnabled: true,SendQuota(Max24HourSend,MaxSendRate,SentLast24Hours),ProductionAccessEnabled
- Path:
Curl Examples
# 1. Verify a domain identity
curl -s -X POST http://localhost:4566/v2/email/identities \
-H "Content-Type: application/json" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/ses/aws4_request, SignedHeaders=host, Signature=fake" \
-d '{"EmailIdentity":"example.com"}'
# 2. List all verified identities
curl -s http://localhost:4566/v2/email/identities \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/ses/aws4_request, SignedHeaders=host, Signature=fake"
# 3. Create an email template
curl -s -X POST http://localhost:4566/v2/email/templates \
-H "Content-Type: application/json" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/ses/aws4_request, SignedHeaders=host, Signature=fake" \
-d '{
"TemplateName": "welcome-email",
"TemplateContent": {
"Subject": "Welcome, {{name}}!",
"Text": "Hi {{name}}, welcome to {{company}}. Your account is ready.",
"Html": "<h1>Welcome, {{name}}!</h1><p>Hi {{name}}, welcome to <strong>{{company}}</strong>.</p>"
}
}'
# 4. Send using a template
curl -s -X POST http://localhost:4566/v2/email/outbound-emails \
-H "Content-Type: application/json" \
-H "Authorization: AWS4-HMAC-SHA256 Credential=test/20260421/us-east-1/ses/aws4_request, SignedHeaders=host, Signature=fake" \
-d '{
"FromEmailAddress": "[email protected]",
"Destination": {"ToAddresses": ["[email protected]"]},
"Content": {
"Template": {
"TemplateName": "welcome-email",
"TemplateData": "{\"name\":\"Alice\",\"company\":\"Acme Corp\"}"
}
}
}'SDK Example
import {
SESv2Client,
CreateEmailIdentityCommand,
SendEmailCommand,
CreateEmailTemplateCommand,
GetAccountCommand,
} from '@aws-sdk/client-sesv2';
const ses = new SESv2Client({
region: 'us-east-1',
endpoint: 'http://localhost:4566',
credentials: { accessKeyId: 'test', secretAccessKey: 'test' },
});
// Verify sender identity
await ses.send(new CreateEmailIdentityCommand({
EmailIdentity: '[email protected]',
}));
// Send a simple email
const { MessageId } = await ses.send(new SendEmailCommand({
FromEmailAddress: '[email protected]',
Destination: {
ToAddresses: ['[email protected]'],
CcAddresses: ['[email protected]'],
},
Content: {
Simple: {
Subject: { Data: 'Order Confirmation #12345', Charset: 'UTF-8' },
Body: {
Text: { Data: 'Your order has been confirmed. Thank you for shopping!', Charset: 'UTF-8' },
Html: {
Data: '<h2>Order Confirmed</h2><p>Your order #12345 has been confirmed. Thank you!</p>',
Charset: 'UTF-8',
},
},
},
},
EmailTags: [
{ Name: 'category', Value: 'transactional' },
{ Name: 'order_id', Value: '12345' },
],
}));
console.log('Message ID:', MessageId);
// Create a template for repeated use
await ses.send(new CreateEmailTemplateCommand({
TemplateName: 'password-reset',
TemplateContent: {
Subject: 'Reset your password',
Text: 'Click this link to reset your password: {{resetLink}}',
Html: '<p>Click <a href="{{resetLink}}">here</a> to reset your password. Link expires in {{expiryMinutes}} minutes.</p>',
},
}));
// Check account sending quotas
const account = await ses.send(new GetAccountCommand({}));
console.log('Daily sending limit:', account.SendQuota?.Max24HourSend);
console.log('Sent in last 24h:', account.SendQuota?.SentLast24Hours);Outbox
Awsim captures every outbound email — SendEmail, SendBulkEmail, SendCustomVerificationEmail — into a SQLite store so you can inspect what was actually sent without parsing the SDK call.
UI: open /ses and switch to the Outbox tab (default). Lists every captured message newest-first, with a search box that filters by subject / from / recipient. Click a row to expand the body — picks the best view automatically (Text → HTML in a sandboxed iframe → Raw). The dialog shows message ID, full To / Cc / Bcc, account, region, and timestamp.
Admin endpoint:
# All captured emails, newest first
curl http://localhost:4566/_awsim/ses/sent | jq .
# Scope to one account / region
curl 'http://localhost:4566/_awsim/ses/sent?account=000000000000®ion=us-east-1'Returns { count, emails: [...] }; each email has messageId, from, to, cc, bcc, subject, bodyText, bodyHtml, raw, sentAt, account, region.
Persistence + retention
- With
--data-dir, the outbox lives in{data-dir}/ses.dband survives restarts. Without it, an ephemeral tempdir holds the DB and is cleaned up on shutdown. - An hourly background sweep deletes emails older than
--ses-retention-hours(default 720h / 30 days). Set to0to disable.
Behavior Notes
- SES uses the REST/JSON v2 API (
/v2/email/...paths), not the legacy form-encodedsesprotocol. - Emails are accepted, recorded into the Outbox, and not actually delivered — no SMTP connection is made.
- Identity verification status is set to
SUCCESSimmediately without DNS verification or email confirmation. - Template variable substitution (
) is stored but not rendered during send in the current implementation. MessageIdis returned as a UUID for each sent email.GetAccountalways reportsSendingEnabled: trueand generous quota limits.- Outbound emails are persisted in SQLite (see Outbox). All other state (identities, templates, contact lists, suppression list) is in-memory only and lost on restart.