Send Scheduled Emails Using Amazon SES & EventBridge - (Let's Build ποΈ Series)
awedis
Posted on August 21, 2024
One of the key aspects to automate is user notifications, especially for recurring events or updates.
In modern applications, decoupling solutions is crucial. A decoupled architecture not only allows for faster upgrades but also enhances scalability, resilience, and ease of maintenance.
In this article, weβll build a simple application that sends an email to the user every morning at 8:00 AM. For this example, we'll keep the content straightforward: a simple 'Good Morning!' message. Without further ado, letβs dive into the cool part.
First, we'll set up an Amazon EventBridge to handle the scheduling. If you'd like to learn more about EventBridge, check out this article: Schedule Lambda Functions Using EventBridge | Serverless
Hereβs a Terraform code snippet that schedules an AWS EventBridge rule to trigger a Lambda function every day at 8:00 AM:
terraform {
required_version = "1.5.1"
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.22.0"
}
}
}
provider "aws" {
region = var.region
}
resource "aws_lambda_function" "email_lambda" {
function_name = "email_lambda"
handler = "main.lambda_handler"
runtime = "python3.8"
role = aws_iam_role.lambda_exec_role.arn
filename = "main.zip"
source_code_hash = filebase64sha256("main.zip")
}
resource "aws_iam_role" "lambda_exec_role" {
name = "lambda_exec_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy_attachment" "lambda_exec_policy" {
role = aws_iam_role.lambda_exec_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_cloudwatch_event_rule" "every_day_8am" {
name = "every_day_8am"
schedule_expression = "cron(0 8 * * ? *)"
}
resource "aws_cloudwatch_event_target" "trigger_lambda" {
rule = aws_cloudwatch_event_rule.every_day_8am.name
target_id = "lambda_target"
arn = aws_lambda_function.email_lambda.arn
}
resource "aws_lambda_permission" "allow_eventbridge" {
statement_id = "AllowExecutionFromEventBridge"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.email_lambda.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.every_day_8am.arn
}
resource "aws_iam_policy" "lambda_policy" {
name = "lambda_policy"
description = "Policy to allow Lambda to send emails using SES"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "ses:SendEmail"
Effect = "Allow"
Resource = "*"
}]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attachment" {
role = aws_iam_role.lambda_exec_role.name
policy_arn = aws_iam_policy.lambda_policy.arn
}
π Note: Ensure that the handler configuration in your Lambda function matches the function signature. If your file is named lambda_function.py, the handler should be configured as lambda_function.lambda_handler.
Here's how you can write a Python script that sends an email using AWS SES inside an AWS Lambda function:
import boto3
from botocore.exceptions import ClientError
def lambda_handler(event, context):
ses_client = boto3.client('ses', region_name='eu-west-1')
sender_email = "your sender email"
recipient_email = "your receiver email"
subject = "Good Morning!"
body_text = "Good Morning!"
email = {
'Source': sender_email,
'Destination': {
'ToAddresses': [
recipient_email,
],
},
'Message': {
'Subject': {
'Data': subject,
},
'Body': {
'Text': {
'Data': body_text,
},
},
},
}
try:
response = ses_client.send_email(**email)
print(f"Email sent! Message ID: {response['MessageId']}")
except ClientError as e:
print(f"Error sending email: {e.response['Error']['Message']}")
return {
'statusCode': 200,
'body': 'Email sent successfully'
}
π Note: Make sure to verify your sender email as well before.
Here is a picture of success once the email was sent:
Here is another picture of EventBridge triggering every morning the Lambda function:
Conclusion
Scheduling jobs is crucial, especially as more tasks require automation. I hope this article serves as a helpful starting point and inspires you to build something truly amazing from it.
If you did like my content, and want to see more, feel free to connect with me on β‘οΈ LinkedIn, happy to guide or help with anything that needs clarification ππ
Posted on August 21, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.