How to send and receive emails with SES using serverless Lambda functions
Original post:
https://www.lambdatv.com/send-and-receive-email-for-serverless-developers
3. What you’ll learn
1. Hello world: sending your first email
2. Using email templates with multiple receivers
3. Ensure email providers trust you (as an email sender)
4. Receive emails and process them with AWS Lambda
14. Sending an email
Permissions for the function. See
https://github.com/jeshan/lambdatv/
blob/master/ses-intro/ses-send-
receive-email-policy-document.json
38. 1 more thing about
DKIM
via amazonses.com or not?
39. Other use cases
- More security: can reject emails based on company policy. Example: only
authenticated emails from certain domains may be received.
- Support team: you can create support tickets on receiving emails at a certain
address with the description as whatever was in the email body.
- Receiving files: You can make it easy for people to send you files, e.g give
them an address to send attachments and use Lambda to process them.
- Archive emails: incoming emails can be saved to S3. for this one, you don’t
need to write a function, it’s supported directly by SES.
To see example functions from AWS that control mail flow:
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action-
lambda-example-functions.html
40. Testing the sending
The emails are like this: x@simulator.amazonses.com where x =
- success
- bounce
- complaint
To learn more:
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/mailbox-
simulator.html
44. Notes
1. Do not use your personal email domain!
2. Ensure priority level for MX is high enough (e.g 0).
3. SES is a per-region service.
4. SES needs the lambda:addPermission IAM permission.
Hi I’m Jeshan and welcome to the 4th episode of Lambda TV where I explore serverless on AWS.
In this video you’ll learn about the basics of sending and receiving email in a serverless application
4 main things that you’ll learn by the end of this video
Before we start, let me quickly give an overview of SES for those who aren’t familiar with it.
Simple Email Service allows you to send and receive email at large scale and at a low cost. You can use it programmatically to send notifications, marketing, transactional emails, etc. You can also accept or reject incoming email according to your custom needs. SES handles a lot of the heavy lifting for you. It was originally built to handle Amazon.com’s email needs so you can be sure that SES will meet your reliability requirements.
Let me walk you through how you can send your first email with AWS Lambda
By default your account is in a sandbox. That means that for now you can only send to addresses that you have verified. So, the first step is to verify an address. Go to the SES console and follow the steps in the screenshot. You may use an address from any email provider at this point.
You’ll get an email as follows
It will then show as status ‘verified’ in the Identity Management section.
Also, you may only use sender addresses on domains that you have verified. So you need to verify a domain as shown in the screenshot.
You may want to take an additional step to secure your emails. You as a new email sender does not have credibility. Emails may have been intercepted by attackers. Or for the rest of us, you may just be a new spammer. Email providers may reject you based on arbitrary rules.
So you need to authenticate your emails. What I’m talking about here is DKIM, meaning: DomainKeys Identified Mail. Like the name suggests, you set it up at domain level by adding DNS records. That’s why I ticked the Generate DKIM Settings at number 4 here.
On the next screen, you’ll get DNS records to enter at your domain registrar. Enter all records shown there.
For example, I would enter my MX record at GoDaddy as follows. SImilarly, enter all the other records shown in the previous slide.
After DNS changes propagates, you may move on on this tutorial…
Next, you create a lambda function as usual
Add some basic info
Also, we’ll create a new role so that the Lambda function has permission to use SES.
(Note that the sendBounce permission will be used later in the tutorial; so you can put it there right now)
No need to type this policy document; you can follow the link on-screen to get it
Finalise the function creation. Next I’m going to show you the code that you can copy paste in there.
The code that you’ll need is at the link on-screen.
The 2 salient points in the function are numbered here. The first is to get a reference to the SES class, then call the sendEmail API.
To test this function, create a test event at the top right and pass in
toAddresses (which can be a string or an array of strings), and a
source (which is an address that the email will appear to originate from).
Click save, then test and you should receive an email like the following.
Congrats, you’ve sent your first email using Amazon SES via Lambda.
Remember that toAddresses property can also be an array. So, this tells you that you can have multiple receivers for the email. Feel free to try it before proceeding.
You may want to keep your email designs separate from your code. In this case, you can use email templates. Usually, you could use a library to handle the templates but it turns out that SES has built-in support for email templates. For example, you can write a template like the above.
What does the name placeholder above tell you? That this template can be used for multiple recipients with each having different values in the placeholders. you can have placeholders as part of the subject. This is useful when sending personalised emails.
The first step is to define a template in a json file. For this tutorial, I saved the following json in a file called example-email-template.json. You can copy it from the github link shown.
You create an email template by calling the createTemplate api.
Later, you can locate all your created templates at the following page (though you currently can’t do much about it from there):
Then create a second json file that will contain the remaining data needed to send an email, like recipients and placeholder values. Here, I put the following json in a file called example-email.json.
The “ReplacementTemplateData” will be read and will take place of the placeholders. You’ll notice that I have 2 recipients, first@email.com and second@email.com and the second one doesn’t have any template data. In this case, the “DefaultTemplateData” will be used as default values for the placeholders.
To send this email, invoke the sendBulkTemplatedEmail api.
As expected, I got 2 emails. The second one had default values of “fellow nerd” and “red” populated.
So far, you’ve seen how to send emails to one or more people and you have also seen how to send personalised emails using templates. Now, you’re going to see how to take action on received email on SES. It was surprising to me that receiving emails has hardly been covered in online tutorials as compared to sending emails.
This is a powerful feature from SES. You can do take actions on the emails like archive them, send notifications. Besides, the ability to integrate with Lambda means that you arbitrarily decide what emails you want to accept, reject, forward, and many more things that you may imagine.
You may have already verified a domain as shown earlier in this tutorial. But just to recap, you need to verify a domain so that SES knows about it. Verify a domain as in the screenshot
I’ll start with a simple example that simply logs incoming emails. Let’s get this simple use case working first and after that, I’m going to show you a slightly more involved example. Create a function with the function showed. I have omitted the slides for it here since I’m sure you can handle this part.
To receive emails with SES, you need certain addresses or domains that you want to monitor. Then you tell SES what Lambda function to process this email. You do both of this in a rule set. You need to create at least one rule in the rule set. So, start creating one as shown here.
Step 1 is to define which verified domains or addresses you want to monitor
Add a Lambda action, then choose the function that you created earlier.
Leave the invocation type as Event. Event is for asynchronous processing, so that means that SES won’t wait for the function execution to complete in order to proceed. After this example is working, I’ll show you how to use RequestResponse.
You may add more actions but I’m going to cover only single-action rules in this tutorial.
Choose a rule name and finalise the rule creation:
Now your rule set is active and ready to accept emails.
Send an email to an address that matches the rule just created. Within a minute or two, you’ll see the log appear in Cloudwatch:
Good. Logging works. We can try a more sophisticated example now.
I’m going to show an example on how you can accept or reject emails based on arbitrary logic. Here, I’ll demonstrate how to reject emails from a certain domain but it can be any criteria you like.
Here, I’ll “reject” the email by sending a bounce back to the original sender.
Change the function body to the one given in the event-request-response.js file.
Here, we’re saying that if we get emails from the jeshan.co domain, we would like to respond with a bounce. Otherwise, proceed with executing the rule set as usual. Change this domain to any other valid one, e.g gmail.com
At the end of the handler, call the callback function with no parameters to indicate normal completion.
The sendBounce function further down looks as follows. You need to set a bounce type, then call the sendBounce api. Maybe you’d also want to give the receiver an explanation of why you made the email bounce. You may also set the disposition to stop_rule_set which won’t execute further rules or actions in the rule set(but in this case it makes no difference since there’s only 1 rule in the rule set).
Before we used the Event invocation type. This called our function asynchronously. But here, we want to control the mail flow so we need to call our function synchronously. You do that by changing the invocation type to RequestResponse.
After you do that, send an email again to a matched recipient from the email domain that you entered in the function.
Sending a stupid email as example here:
After a few seconds, you should get a bounce like the following:
“We’re rejecting your email because your domain sucks”
By the way, you’re seeing in the screenshots that sometimes the “via amazonses.com” is shown (don’t know how other providers handle this). This is because my sender address was from a domain that I didn’t have DKIM set up. If you don’t want people to see this, it will serve you well to set up DKIM from the get-go as I showed in the beginning.
Now, hopefully you get the picture of how arbitrary email processing works with Lambda. I’m sure you can imagine many more use cases. Lambda and Simple Notification Service (SNS) serve as your extension points here. So anything you can do with Lambda or SNS can be combined with SES. Here are some ideas you can consider:
(read the slides)
By the way other integrations are supported but I focus on Lambda because, well, this channel is called LambdaTV :)
Use the mailbox simulator to test scenarios like bounces and complaints. It will especially be useful if you use SES alongside SNS. Otherwise, it won’t be that useful because SNS is the primary way of receiving notifications from the simulator.
The emails are like this: ….. x@simulator.amazonses.com where x =
success
bounce
Complaint
It is recommended that you monitor your email activity, especially for numbers like bounce, complaint and reject rates. If your emails are perceived as spam but keep on sending emails, SES or email providers will penalise you. You should have a mechanism to handle bounces, complaints and rejects. AWS will ask you if you have these when going to production.
You can monitor these things via the API or also in the console at the following dashboards. Here’s the first:
… and the second.
To learn more, watch the videos that I’ll link to at the end. Very important before going to production.
… speaking of which:
Restrictions apply by default because AWS needs to protect the credibility of SES with email providers. To send to any addresses, not just to those that you verified, you need to request production access as described in the following link.
And some things to keep in mind while following this tutorial:
Do not use your personal email domain! I used my personal email domain to send and receive emails with SES, not realising that this was preventing me from receiving any emails in regular inbox at Google. Don’t be as stupid as me.
Ensure priority level for MX is high enough (e.g 0). The mistake I did was using something other than 0 and waiting for hours to get my Lambda function to get invoked… only to realise later that another higher priority MX record was being chosen.
SES is a per-region service so any configuration applies per region, even verified emails and domains.
SES needs the lambda:addPermission IAM permission. This is done automatically if you’re creating rule sets via the SES console but it may not be the case through the API.
I have chosen these 2 re:Invent sessions for you to learn about it in more detail. You’ll learn many things from AWS people, including high-level discussion on implementing use cases and handling cases like bounces and complaints. The latter are very important for your credibility.
Click the image on the slides to get access the videos.
You can find all code discussed in this video at the github link on screen.
If you want access to the guide and all resources mentioned, head over to the website at the link on screen
Hope you liked this tutorial. If you like such videos about integrating serverless with AWS services and would like to see more, subscribe below. Thanks!