Secure AWS SES Email Sending - Policy Design & Implementation Guide

Amazon Simple Email Service (SES) is a powerful tool for sending transactional emails, but misconfigured policies can lead to abuse, such as phishing attacks or spam campaigns. This article explains how to create a secure SES policy that balances flexibility and security, while preventing unauthorised use.
We’ll cover:
- Why default policies are risky
- SES identity and configuration set setup
- Step-by-step policy configuration
- Best practices for IAM groups and users
Key Risks of Unsecured SES Policies
- Email Spoofing: Attackers could send emails from unauthorised addresses (e.g.,
[email protected]). - IP Spoofing: Malicious actors might bypass source IP restrictions.
- Data Exfiltration: Large email attachments could be exploited to leak sensitive data.
- Reputation Damage: Unrestricted sending to unvetted recipients can harm your domain’s email reputation.
The Secure SES Policy Explained
Below is a policy that mitigates these risks. We’ll explain each component and explain its purpose.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SESSendingPermissions",
"Effect": "Allow",
"Action": "ses:SendRawEmail",
"Resource": [
"arn:aws:ses:eu-west-3:000000000000:identity/yourdomain.com",
"arn:aws:ses:eu-west-3:000000000000:configuration-set/go-yourdomain"
],
"Condition": {
"StringLike": {
"ses:FromAddress": "[email protected]"
},
"IpAddress": {
"aws:SourceIp": "123.123.123.123/32"
},
"Bool": {
"ses:RequireTLS": "true"
},
"NumericLessThanEquals": {
"ses:MessageSize": "10485760"
}
}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SESSendingPermissions",
"Effect": "Allow",
"Action": "ses:SendRawEmail",
"Resource": [
"arn:aws:ses:eu-central-1:123456789012:identity/*",
"arn:aws:ses:eu-central-1:123456789012:configuration-set/*",
],
"Condition": {
"StringLike": {
"ses:FromAddress": [
"*@domain1.com",
"*@domain2.com"
]
},
"IpAddress": {
"aws:SourceIp": [
"123.123.123.123",
"456.456.456.456"
]
}
}
}
]
}AWS SES Identity and Configuration Setup
Before implementing the policy, ensure your SES resources are properly configured.
1. Verify SES Identity
A SES identity is a domain or email address authorised to send emails via AWS SES.
Domain Verification (Recommended)
- Go to the AWS SES Console → Verified Identities.
- Click Create Identity → Select Domain.
- Enter your domain (e.g.,
yourdomain.com). - Follow the instructions to add a all the DNS records to your DNS provider to prove ownership.
- Enable DKIM (DomainKeys Identified Mail) to prevent email spoofing:
- SES provides CNAME records to add to your DNS.
- DKIM adds a digital signature to your emails, ensuring recipients trust your domain.
- DMARC - Add the suggested DMARC records.
Email Address Verification (Optional)
For testing, you can verify individual addresses (e.g., [email protected]), but domain verification is more scalable.
2. Create a Configuration Set
A configuration set defines how SES handles email events (e.g., bounces, opens) and metadata.
- Go to SES Console → Configuration Sets → Create Configuration Set.
- Name it (e.g.,
go-yourdomain). - Add event destinations (optional but recommended):
- SNS Topic: Send bounce/complaint notifications to an SNS topic.
- CloudWatch Metrics: Track sending metrics.
- Note the ARN:
arn:aws:ses:eu-west-3:000000000000:configuration-set/go-yourdomain.
Step-by-Step Policy Setup
1. Create IAM Policy
- Go to IAM Console → Policies → Create Policy.
- Paste the JSON policy above, replacing:
yourdomain.comwith your verified domain- 123.123.123.123 with your trusted IP
[email protected]with your approved sendergo-yourdomain.comwith your configuration set name
2. Create IAM Group & User
Create Group
- Name:
SES-Secure-Senders - Attach the policy created above.
- Name:
Create User
- Name:
smtp-go-yourdomain.com - Assign to the
SES-Secure-Sendersgroup. - Security Tip: Use IAM Roles instead of long-lived credentials where possible.
- Name:
Policy Breakdown: Why Each Restriction Matters
1. Explicit Sender Address (ses:FromAddress)
- What it does: Restricts sending to
[email protected]. - Why it matters: Prevents attackers from forging emails from other addresses (e.g.,
[email protected]).
2. Source IP Restriction (aws:SourceIp)
- What it does: Only allows requests from
123.123.123.123. - Why it matters: Blocks requests from untrusted networks, such as compromised servers.
3. TLS Enforcement (ses:RequireTLS)
- What it does: Ensures emails are encrypted during transit.
- Why it matters: Prevents interception of sensitive data.
4. Message Size Limit (ses:MessageSize)
- What it does: Caps emails at 10MB.
- Why it matters: Stops abuse via oversized payloads.
5. Recipient Whitelisting Optional(ses:Recipients)
- What it does: Only allows emails to
*@trusted-domain.comand[email protected]. - Why it matters: Prevents spam campaigns.
Best Practices for Ongoing Security
1. Monitor SES Metrics
- Set CloudWatch Alarms for:
- Sudden spikes in
SendRawEmailAPI calls - High bounce/complaint rates
- Sudden spikes in
2. Rotate Credentials
- Use AWS STS for temporary credentials (avoid IAM user passwords/API keys).
3. Audit Configuration Sets
- Ensure the
go-yourdomainconfiguration set only logs events to authorised S3 buckets/SNS topics.
4. Test Your Policy
- Use the AWS CLI to validate permissions:
aws ses send-raw-email --from "[email protected]" --destinations "[email protected]" --raw-message file://test-email.txt
Further notes
This policy provides a defence-in-depth approach to securing AWS SES by:
- Restricting senders/recipients
- Enforcing encryption and message limits
- Isolating trusted IPs
This strategy will help reduce the risk of email abuse. A final tip, review IAM policies on a regular basis to catch unintended permissions issues.
