install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/TerminalSkills/skills/aws-ses" ~/.claude/skills/comeonoliver-skillshub-aws-ses && rm -rf "$T"
manifest:
skills/TerminalSkills/skills/aws-ses/SKILL.mdsource content
AWS SES
Amazon Simple Email Service (SES) is a cost-effective email platform for sending transactional, marketing, and notification emails. It also receives incoming email and integrates with S3, SNS, and Lambda for processing.
Core Concepts
- Verified Identity — domain or email address authorized to send
- Configuration Set — tracking settings for opens, clicks, bounces
- Template — reusable email template with variable substitution
- Receipt Rule — rules for processing incoming emails
- Suppression List — addresses that bounced or complained
- Sending Quota — rate limits based on account reputation
Domain Verification
# Verify a domain (creates DKIM records) aws sesv2 create-email-identity --email-identity example.com
# Get DKIM tokens to add as DNS CNAME records aws sesv2 get-email-identity --email-identity example.com \ --query 'DkimAttributes.Tokens'
# Verify a single email address (for testing) aws sesv2 create-email-identity --email-identity test@example.com
# List verified identities aws sesv2 list-email-identities --query 'EmailIdentities[].IdentityName'
Sending Email
# Send a simple email aws sesv2 send-email \ --from-email-address "noreply@example.com" \ --destination '{"ToAddresses":["user@example.com"]}' \ --content '{ "Simple": { "Subject": {"Data": "Order Confirmation #12345"}, "Body": { "Html": {"Data": "<h1>Thank you!</h1><p>Your order has been confirmed.</p>"}, "Text": {"Data": "Thank you! Your order has been confirmed."} } } }' \ --configuration-set-name prod-tracking
# Send email with boto3 import boto3 ses = boto3.client('sesv2') ses.send_email( FromEmailAddress='noreply@example.com', Destination={ 'ToAddresses': ['user@example.com'], 'BccAddresses': ['archive@example.com'] }, Content={ 'Simple': { 'Subject': {'Data': 'Your Invoice'}, 'Body': { 'Html': {'Data': '<h1>Invoice #INV-001</h1><p>Amount: $99.99</p>'}, 'Text': {'Data': 'Invoice #INV-001\nAmount: $99.99'} } } }, ConfigurationSetName='prod-tracking' )
Email Templates
# Create a template aws sesv2 create-email-template \ --template-name order-confirmation \ --template-content '{ "Subject": "Order Confirmation #{{orderNumber}}", "Html": "<h1>Hi {{customerName}},</h1><p>Your order #{{orderNumber}} for {{itemName}} has been confirmed.</p><p>Total: ${{total}}</p>", "Text": "Hi {{customerName}},\nYour order #{{orderNumber}} for {{itemName}} has been confirmed.\nTotal: ${{total}}" }'
# Send using a template aws sesv2 send-email \ --from-email-address "orders@example.com" \ --destination '{"ToAddresses":["user@example.com"]}' \ --content '{ "Template": { "TemplateName": "order-confirmation", "TemplateData": "{\"orderNumber\":\"12345\",\"customerName\":\"Alice\",\"itemName\":\"Widget Pro\",\"total\":\"99.99\"}" } }'
# Bulk templated sending with boto3 import boto3 ses = boto3.client('sesv2') ses.send_bulk_email( FromEmailAddress='marketing@example.com', DefaultContent={ 'Template': { 'TemplateName': 'weekly-newsletter', 'TemplateData': '{"week":"Jan 15"}' } }, BulkEmailEntries=[ { 'Destination': {'ToAddresses': ['alice@example.com']}, 'ReplacementEmailContent': { 'ReplacementTemplate': { 'ReplacementTemplateData': '{"name":"Alice","recommendations":"Widget A, Widget B"}' } } }, { 'Destination': {'ToAddresses': ['bob@example.com']}, 'ReplacementEmailContent': { 'ReplacementTemplate': { 'ReplacementTemplateData': '{"name":"Bob","recommendations":"Gadget X, Gadget Y"}' } } } ], ConfigurationSetName='marketing-tracking' )
Bounce and Complaint Handling
# Create a configuration set with event destinations aws sesv2 create-configuration-set --configuration-set-name prod-tracking # Add SNS destination for bounces and complaints aws sesv2 create-configuration-set-event-destination \ --configuration-set-name prod-tracking \ --event-destination-name bounce-handler \ --event-destination '{ "Enabled": true, "MatchingEventTypes": ["BOUNCE", "COMPLAINT"], "SnsDestination": { "TopicArn": "arn:aws:sns:us-east-1:123456789:ses-bounces" } }'
# Lambda handler for bounce/complaint SNS notifications import json def handler(event, context): for record in event['Records']: message = json.loads(record['Sns']['Message']) notification_type = message['notificationType'] if notification_type == 'Bounce': bounce = message['bounce'] for recipient in bounce['bouncedRecipients']: email = recipient['emailAddress'] bounce_type = bounce['bounceType'] # Permanent or Transient if bounce_type == 'Permanent': suppress_email(email) elif notification_type == 'Complaint': complaint = message['complaint'] for recipient in complaint['complainedRecipients']: unsubscribe_email(recipient['emailAddress'])
Receiving Email
# Create a receipt rule set aws ses create-receipt-rule-set --rule-set-name inbound-rules aws ses set-active-receipt-rule-set --rule-set-name inbound-rules
# Create rule to store incoming email in S3 and trigger Lambda aws ses create-receipt-rule \ --rule-set-name inbound-rules \ --rule '{ "Name": "process-support-emails", "Enabled": true, "Recipients": ["support@example.com"], "Actions": [ {"S3Action": {"BucketName": "incoming-email", "ObjectKeyPrefix": "support/"}}, {"LambdaAction": {"FunctionArn": "arn:aws:lambda:us-east-1:123456789:function:process-support-email"}} ] }'
Monitoring
# Check sending quota and statistics aws sesv2 get-account --query '{SendQuota:SendQuota,SendingEnabled:SendingEnabled}'
# Get sending statistics aws ses get-send-statistics --query 'SendDataPoints[-5:]'
Best Practices
- Always verify domains with DKIM for better deliverability
- Set up bounce and complaint handling before sending at scale
- Use configuration sets to track delivery metrics
- Send from a subdomain (mail.example.com) to protect main domain reputation
- Include unsubscribe headers in marketing emails (required by law)
- Warm up new accounts gradually — start with small volumes
- Use the suppression list API to respect bounces and complaints
- Test with the SES mailbox simulator before going to production