Send e-mail using SES via Lambda function & connect with SQS request (AWS, Python, Emails,)
Most email providers come with the limitation of daily outgoing emails as for example Gmail limited with a maximum outgoing email limit of 3000 only. To scale up from this point the best solution is to use the AWS SES server which gives 50 000 emails per day and 14 emails per second for outgoing as starting average rate.
The following guide, it will show how to set up AWS SES with Lambda connection successfully.
Requirments
Step 1 - Create AWS SES
Amazon Simple Email Service Classic - Follow the following simple steps to create an identity.
* Choose identity type as "Email address", then enter preferred marketing email address in the text field and create an identity (marketing@example.com).
Step 2 - Create AWS Lambda
Create Lambda function with runtime Python 3.8, in options as execution role choose "Create a new role with basic Lambda permissions" & rest fo the advance settings leave it blank.
Refer to the following link to view SES send_email function in AWS SDK for Python
And create lambda function with below snip code
import json
import boto3
from botocore.exceptions import ClientError
def lambda_handler(event, context):
emailData = event['Records'][0]["messageAttributes"]
# print(emailData['fromName'])
# Replace sender@example.com with your "From" address.
# This address must be verified with Amazon SES.
SENDER = emailData['fromName']['stringValue'] + " <marketing@example.com>"
# Replace recipient@example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = emailData['toEmail']['stringValue']
print (emailData)
if 'toCCEmail' in emailData:
CC_RECIPIENT = emailData['toCCEmail']['stringValue']
DESTINATION={
'ToAddresses': [
RECIPIENT,
],
'CcAddresses': [
CC_RECIPIENT,
],
'BccAddresses': [
'marketingcc@example.com',
]
}
else:
DESTINATION = {
'ToAddresses': [
RECIPIENT,
],
'BccAddresses': [
'marketingcc@example.com',
]
}
# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
#CONFIGURATION_SET = "ConfigSet"
# If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
AWS_REGION = "ap-southeast-2"
# The subject line for the email.
SUBJECT = emailData['subject']['stringValue']
# The email body for recipients with non-HTML email clients.
# BODY_TEXT = ("Amazon SES Test (Python)\r\n"
# "This email was sent with Amazon SES using the "
# "AWS SDK for Python (Boto)."
# )
# The HTML body of the email.
BODY_HTML = emailData['body']['stringValue']
# The character encoding for the email.
CHARSET = "UTF-8"
# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
# Try to send the email.
try:
#Provide the contents of the email.
response = client.send_email(
Destination = DESTINATION,
Message={
'Body': {
'Html': {
'Charset': CHARSET,
'Data': BODY_HTML,
},
# 'Text': {
# 'Charset': CHARSET,
# 'Data': BODY_TEXT,
# },
},
'Subject': {
'Charset': CHARSET,
'Data': SUBJECT,
},
},
Source=SENDER,
# If you are not using a configuration set, comment or delete the
# following line
#ConfigurationSetName=CONFIGURATION_SET,
)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:")
print(response['MessageId'])
print(RECIPIENT)
return {
'statusCode': 200,
'body': json.dumps(response)
}
"SENDER" needs to declare confirmed email identity between "< > " brackets, if the system requires multiple outgoing emails, it can be pass through the SQS data but in this scenario, SES confirmed identify email hardcoded in the lambda function.
"DESTINATION " created with two options, one option to include CC emails and the other option to send emails without CC
Recommended by LinkedIn
* To check & store outgoing emails there is an option to connect with AWS S3 but as an easy solution all the emails are BCC into different email address which can access anytime also will be easy to search for outgoing emails through the email server
"Message - Body" comes with two options "Html" or "Text", depending on the requirement it should be chosen for the outgoing emails
Step 3 - Create Two SQS
AWS SQS (for this process required two SQS)
Create another new IAM Account to access SQS
In AWS IAM Console create a new User with Programmatic access & grant the AWS policies as follow (Name: SQS_User)
Update previously created SQS (OutgoingEmailQueue) Access policy (Permissions) to gain access via newly created IAM Account. Eg:
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__owner_statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::account_id:root"
},
"Action": "SQS:*",
"Resource": "arn:aws:sqs:region_code:account_id:OutgoingEmailQueue"
},
{
"Sid": "__sender_statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::account_id:user/SQS_User"
},
"Action": "SQS:SendMessage",
"Resource": "arn:aws:sqs:region_code:account_id:OutgoingEmailQueue"
}
]
}
Connect SQS (OutgoingEmailQueue) with Dead Letter Queue
Choose the dead letter queue option in OutgoingEmailQueue SQS. Press the edit button then select option enabled, It will open up to search for other SQS listed in your account in the same region. Select previously created "OutgoingEmailFailedQueue" SQS in a dead letter queue option and press save.
If any further question related to this scenario, Please add in the comment section, I will try my best to answer. Also if this article useful for development don't forget to leave feedback in the comment section.
Stop Complaining & Start with Implementation
Thank you
Gayan Jayanath
I do not know why do you stop at step Connect SQS (OutgoingEmailQueue) with Dead Letter Queue. Can you continue update this post with more detail
Thanks for your article. I have a question - why do you need to set up a new IAM user? Can you just add permissions to an existing user? Thanks