AWS SES: Email Service Integration
Amazon Simple Email Service (SES) is a scalable, cost-effective email platform that lets you send transactional emails, marketing messages, and notifications. This guide walks through integrating SES into your applications with practical examples.
Why Choose Amazon SES?
- Cost-effective: Pay only for what you send ($0.10 per 1,000 emails at time of writing).
- Scalable: Handles anything from a handful to millions of emails.
- Deliverability: Built-in reputation management and dedicated IP options.
- Integration: Works seamlessly with other AWS services (SNS, Lambda, S3).
Prerequisites
Before you begin, ensure you have:
- An AWS account with appropriate IAM permissions.
- A verified domain or email address.
- AWS SDK installed for your language of choice.
Step 1: Verify Your Identity
SES requires you to verify ownership of the domain or email address you send from.
# Verify a single email address
aws ses verify-email-identity --email-address sender@example.com
# Verify an entire domain
aws sesv2 create-email-identity --email-identity example.com
For domain verification, add the returned DKIM CNAME records to your DNS provider. This improves deliverability and prevents spoofing.
Step 2: Move Out of the Sandbox
New accounts start in the SES sandbox, which restricts you to verified recipients and low sending limits. To send to arbitrary addresses, request production access via the AWS Console under SES > Account dashboard > Request production access.
Step 3: Sending Email with the SDK
Here's a Python example using boto3:
import boto3
from botocore.exceptions import ClientError
client = boto3.client("ses", region_name="us-east-1")
def send_email(sender, recipient, subject, body_html):
try:
response = client.send_email(
Source=sender,
Destination={"ToAddresses": [recipient]},
Message={
"Subject": {"Data": subject, "Charset": "UTF-8"},
"Body": {
"Html": {"Data": body_html, "Charset": "UTF-8"}
},
},
)
print(f"Email sent! Message ID: {response['MessageId']}")
except ClientError as e:
print(f"Error: {e.response['Error']['Message']}")
send_email(
sender="sender@example.com",
recipient="recipient@example.com",
subject="Welcome!",
body_html="<h1>Hello</h1><p>Thanks for signing up.</p>",
)
Step 4: Using Configuration Sets
Configuration sets let you track email events (bounces, complaints, deliveries) and publish them to SNS, CloudWatch, or Kinesis Firehose.
aws ses create-configuration-set \
--configuration-set Name=my-config-set
aws ses create-configuration-set-event-destination \
--configuration-set-name my-config-set \
--event-destination '{
"Name": "sns-destination",
"Enabled": true,
"MatchingEventTypes": ["bounce", "complaint"],
"SNSDestination": {"TopicARN": "arn:aws:sns:us-east-1:123456789012:ses-events"}
}'
Reference the configuration set when sending:
response = client.send_email(
Source=sender,
Destination={"ToAddresses": [recipient]},
Message={...},
ConfigurationSetName="my-config-set",
)
Step 5: Handling Bounces and Complaints
Managing bounces and complaints is critical to maintaining a healthy sender reputation. AWS may pause your account if these rates exceed thresholds (5% bounce, 0.1% complaint).
A typical pattern:
- Configure SES to publish bounce/complaint notifications to an SNS topic.
- Subscribe a Lambda function to the topic.
- In the Lambda, remove problematic addresses from your mailing list.
import json
def lambda_handler(event, context):
for record in event["Records"]:
message = json.loads(record["Sns"]["Message"])
notification_type = message["notificationType"]
if notification_type == "Bounce":
for recipient in message["bounce"]["bouncedRecipients"]:
suppress_address(recipient["emailAddress"])
elif notification_type == "Complaint":
for recipient in message["complaint"]["complainedRecipients"]:
suppress_address(recipient["emailAddress"])
def suppress_address(email):
# Add to your suppression list / database
print(f"Suppressing {email}")
Best Practices
- Use DKIM and SPF: Authenticate your emails to avoid spam folders.
- Set up a suppression list: Use SES account-level suppression to automatically skip known bad addresses.
- Monitor your reputation: Watch the SES reputation dashboard and CloudWatch metrics.
- Warm up dedicated IPs: Gradually increase volume to build a positive sending history.
- Throttle intelligently: Respect your maximum send rate to avoid throttling errors.
Cost Considerations
| Item | Cost |
|---|---|
| Outbound emails | $0.10 per 1,000 |
| Attachments/data | $0.12 per GB |
| Dedicated IP | ~$24.95/month |
| Inbound emails | $0.10 per 1,000 |
Always check the current pricing as rates may change.
Conclusion
Amazon SES provides a robust, affordable foundation for s
Top comments (0)