SES

Amazon Simple Email Service (SES) is a cloud-based email-sending service designed to send transactional, promotional, or bulk emails reliably and affordably. It integrates seamlessly with other AWS services and supports features like email tracking, templates, and dedicated IPs.
Author

Benedict Thekkel

1. Key Features of AWS SES

  1. Transactional Emails: Send purchase confirmations, password resets, etc.
  2. Promotional Emails: Send marketing or newsletter emails.
  3. Bulk Emails: Deliver emails to large subscriber lists.
  4. Email Tracking: Monitor deliveries, opens, clicks, bounces, and complaints.
  5. Templates: Create reusable email templates for faster development.
  6. Customizable Sender Domains: Use verified domains or email addresses.
  7. DKIM and SPF Support: Ensure emails aren’t marked as spam.
  8. SMTP and API Access: Use SES with your email client or custom applications.

2. Setting Up AWS SES

Step 1: Verify Email or Domain

  1. Open the SES Console.
  2. Choose Verify a New Email Address or Verify a New Domain.
    • For domain verification:
      • Add TXT and optionally CNAME records to your DNS.
      • Enable DKIM for better email deliverability.
  3. After verification, you can start sending emails from the verified email/domain.

Step 2: Request Production Access

By default, AWS SES operates in a sandbox environment, limiting sending to verified emails. To send emails to unverified recipients: 1. Request production access via the AWS Support Center.


3. Using AWS SES

Sending Email via AWS Management Console

  1. Navigate to the SES Console.
  2. Choose Email Sending > Send Test Email.
  3. Fill in the recipient, subject, and body, and click Send.

4. Sending Email Programmatically

Using AWS SDK for Python (Boto3)

Install Boto3:

pip install boto3

Example Code:

pip install boto3
Requirement already satisfied: boto3 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (1.35.90)
Requirement already satisfied: botocore<1.36.0,>=1.35.90 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (from boto3) (1.35.90)
Requirement already satisfied: jmespath<2.0.0,>=0.7.1 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (from boto3) (1.0.1)
Requirement already satisfied: s3transfer<0.11.0,>=0.10.0 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (from boto3) (0.10.4)
Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (from botocore<1.36.0,>=1.35.90->boto3) (2.9.0.post0)
Requirement already satisfied: urllib3!=2.2.0,<3,>=1.25.4 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (from botocore<1.36.0,>=1.35.90->boto3) (2.3.0)
Requirement already satisfied: six>=1.5 in /home/proxmox-ml5/miniconda/envs/fast/lib/python3.12/site-packages (from python-dateutil<3.0.0,>=2.1->botocore<1.36.0,>=1.35.90->boto3) (1.17.0)
Note: you may need to restart the kernel to use updated packages.
import boto3
from botocore.exceptions import NoCredentialsError, PartialCredentialsError
# Initialize SES client
ses_client = boto3.client('ses', region_name='ap-southeast-2')
# Email parameters
# Email details
SENDER = "mail@benedictthekkel.com"  # Replace with your verified sender email
RECIPIENT = "benthekkel@gmail.com"  # Replace with your verified recipient email
SUBJECT = "Test Email from AWS SES 5(Sandbox)"
BODY_TEXT = "This is a test email sent through AWS SES using the sandbox environment."
BODY_HTML = """
<html>
<head></head>
<body>
  <h1>AWS SES Test Email</h1>
  <p>This is a test email sent through AWS SES using the sandbox environment.</p>
</body>
</html>
"""

# Function to send email
try:
    response = ses_client.send_email(
        Source=SENDER,
        Destination={"ToAddresses": [RECIPIENT]},
        Message={
            "Subject": {"Data": SUBJECT},
            "Body": {
                "Text": {"Data": BODY_TEXT},
                "Html": {"Data": BODY_HTML},
            },
        },
    )
    print("Email sent! Message ID:", response["MessageId"])
except NoCredentialsError:
    print("Error: No AWS credentials found.")
except PartialCredentialsError:
    print("Error: Incomplete AWS credentials.")
except Exception as e:
    print(f"Error: {e}")
Email sent! Message ID: 0108019482f70eaa-4cbab973-c27e-4229-8248-1a3e6ded042d-000000

Using the SES SMTP Interface

  1. Generate SMTP credentials via SES Console > SMTP Settings.
  2. Use an email library like smtplib in Python.

Example Code:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# SMTP details
smtp_server = "email-smtp.ap-southeast-2.amazonaws.com"
port = 587
username = "<username>"
password = "<password>"

# Email details
SENDER = "mail@benedictthekkel.com"  # Replace with your verified sender email
RECIPIENT = "benthekkel@gmail.com"  # Replace with your verified recipient email
subject = "SMTP Test Email"
body = "This email was sent using AWS SES SMTP."

# Create message
message = MIMEMultipart()
message['From'] = SENDER
message['To'] = RECIPIENT
message['Subject'] = subject
message.attach(MIMEText(body, 'plain'))

# Send email
with smtplib.SMTP(smtp_server, port) as server:
    server.starttls()
    server.login(username, password)
    server.send_message(message)

print("Email sent successfully!")

5. Advanced Features

Tracking Deliverability

  • Enable email feedback forwarding to handle bounces and complaints.
  • Use SNS notifications to get alerts for delivery status.
    • Example: Set up an SNS topic for bounce notifications and subscribe via Lambda or email.

Using Templates

Create a reusable template:

aws ses create-template --cli-input-json '{
  "Template": {
    "TemplateName": "MyTemplate",
    "SubjectPart": "Hello {{name}}",
    "TextPart": "Hi {{name}}, this is a plain text email.",
    "HtmlPart": "<h1>Hi {{name}},</h1><p>This is an HTML email.</p>"
  }
}'

Send an email using the template:

response = ses_client.send_templated_email(
    Source=sender,
    Destination={'ToAddresses': [recipient]},
    Template="MyTemplate",
    TemplateData='{"name":"John"}'
)

print("Email sent! Message ID:", response['MessageId'])

6. Monitoring and Metrics

  • Use CloudWatch to monitor:
    • Delivery rate
    • Bounce rate
    • Complaint rate
  • Set alarms for thresholds.

7. Pricing

  • Email Sending:
    • $0.10 per 1,000 emails sent.
    • Free for emails sent from EC2 instances (limits apply).
  • Attachment Size:
    • Additional costs for larger payloads (charged per GB).

8. Best Practices

  1. Use Verified Domains: Improves deliverability and avoids spam issues.
  2. DKIM and SPF: Configure for authentication.
  3. Monitoring: Set up CloudWatch and SNS for delivery insights.
  4. Content Personalization: Use templates to customize emails.
  5. Backup Logs: Store delivery logs in S3 for auditing.
Back to top