-
Notifications
You must be signed in to change notification settings - Fork 204
Guide to using AWS Lambda with AWS Simple Email Service #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,6 +77,7 @@ something to S3 on each execution cycle you could rack up the bill! | |
* [Use the callback parameter with node v4.3](#the-callback-parameter) | ||
* [Trigger a Lambda function using an event from DynamoDB](#triggering-a-lambda-function-using-an-event-from-dynamodb) | ||
* [Trigger a Lambda function using the Simple Notification System](#trigger-a-lambda-function-using-the-simple-notification-system) | ||
* [Trigger a Lambda function when an email comes in to the AWS Simple Email Service (SES)](#trigger-a-lambda-function-when-an-email-is-received-by-amazon-simple-email-service) | ||
* [Continuous Integration using Codeship](#continuous-integration-using-codeship) | ||
* [Testing Lambda Functions](#testing-lambda-functions) | ||
* [Upload Lambda Function to S3 and deploy to Lambda](#upload-your-lambda-function-to-an-s3-bucket-and-automatically-deploy-it-to-lambda-bash-script-example) | ||
|
@@ -765,6 +766,119 @@ NB: Using the JSON Messsage Generator option it is possible to format messages d | |
|
||
More info and an example can be found [here](https://aws.amazon.com/blogs/compute/continuous-integration-deployment-for-aws-lambda-functions-with-jenkins-and-grunt-part-1/) | ||
|
||
### Trigger a Lambda function when an email is received by Amazon Simple Email Service | ||
|
||
Start by creating a blank AWS Lambda function that will be called whenever a new email comes in. | ||
|
||
#### Set up SES | ||
For this you need your own domain, and you need to verify the domain with AWS, this can take up to 72hrs, so have a nice drink and chill out while you wait :sunglasses: :coffee: | ||
|
||
See here for how: http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domain-procedure.html | ||
|
||
#### Add a rule set | ||
Click `rule sets` on the bottom left and create a new rule set with whatever name you like. If you want to have your function triggered by emails sent to any address in your domain you can leave recipient blank, else you can add the recipient you want to trigger the function. | ||
|
||
In that rule set add an action for your Lambda function. This tells AWS to run your action when an email is received by SES. | ||
|
||
This is all you need to do to make your function trigger from SES, but depending on what your Lambda function does, it might be kind of hard to verify that it's run (though you can look at the stats for the function to see how and when it's been run) so let's make it save the body of your email to your bucket! | ||
|
||
### Warning before continuing | ||
|
||
This next section is an illustration of how Lambda function can be used with SES, not a recommendation for usage. | ||
If you set this up on your own AWS account, it's possible a SPAMer will _flood_ your Lambda and cause you to waste _loadz-a-money_ on S3 writes... | ||
|
||
 | ||
**$0.05 per 1,000** writes to S3 might not _sound_ like a lot, but it will add up if you consider the volume of spam sent/received. (_if you use GMail you won't realise it because Google has **amazing** filters, but an "un-protected" email address will get hundreds and a reasonably popular domain will get **thousands** of SPAM emails **per day**_) | ||
|
||
> Fun Fact: Over 50% of email is SPAM see: https://www.statista.com/statistics/420391/spam-email-traffic-share/ | ||
 | ||
|
||
Continue with care :dollar: | ||
|
||
#### Save the email to S3 | ||
|
||
Go back to the rule set you created for your Lambda function. Add a new action to it, this one should be an S3 action, with the bucket you want to use selected. This will save the email to S3. Make sure this action is positioned **above** your Lambda function: | ||
|
||
 | ||
|
||
This saves the email in a slightly weird way that we don't have that much control over, so we want our Lambda function to take the file written from the S3 action and process it separately. | ||
|
||
Before this can happen you need to set up a role to give your function access to S3, for the policy of the role put something like this: | ||
|
||
```json | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Effect": "Allow", | ||
"Action": "logs:CreateLogGroup", | ||
"Resource": "arn:aws:logs:us-east-2:YOUR-USER-ID-HERE:*" | ||
}, | ||
{ | ||
"Effect": "Allow", | ||
"Action": [ | ||
"logs:CreateLogStream", | ||
"logs:PutLogEvents", | ||
"s3:*" | ||
], | ||
"Resource": [ | ||
"arn:aws:logs:us-east-2:271861816104:log-group:/aws/lambda/getHelloWorld:*", | ||
"arn:aws:s3:::YOUR-BUCKET-HERE", | ||
"arn:aws:s3:::YOUR-BUCKET-HERE/*" | ||
] | ||
} | ||
] | ||
} | ||
``` | ||
|
||
The `s3:*` property under `Action` allows all s3 functionality for any functions with this role. The last two properties under `Resource` give access to your bucket and any subdirectories within it. | ||
|
||
In the permissions tab of your S3 bucket select "Any Authenticated AWS User" and give read and write access for object access and permission access. | ||
|
||
(I'm sure there is a better way than this, __please__ raise an issue if you know how :pray:) | ||
|
||
So now when we receive an email it is save to S3 and a function is triggered. Next we need we need to hook the two up so our Lambda function reads the saved file, and saves the body in a nice readable way. | ||
|
||
#### Save the body to S3 using AWS Lambda | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we save all incoming emails it's possible for a SPAMer to flood our Lambda and cause us to waste loadz-a-money on S3 writes ...
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added a note with some of the above comment before the S3 section. Should hopefully help to deter people from leaving this set up on their own accounts. A better exercise could be to process the email with Lambda before saving to S3 so we could run something more interesting like a check for a certain keyword or something like that. |
||
To do this we can change our Lambda function to look like this: | ||
|
||
```js | ||
var AWS = require('aws-sdk'); | ||
var s3 = new AWS.S3( { | ||
signatureVersion: 'v4' | ||
} ); //Make a new instance of the AWS.S3 object, telling it which signature version to use | ||
|
||
|
||
exports.handler = (event, context, callback) => { | ||
s3.getObject({ //get the saved object from your S3 bucket | ||
Bucket: YOUR-BUCKET-NAME-HERE, | ||
Key: 'YOUR-SUBDIRECTORY-THAT-S3-SAVES-TO/' + event.Records[0].ses.mail.messageId | ||
}, (err, res) => { //The contents of the file will be passed into the callback as res | ||
|
||
const params = { | ||
Bucket: BUCKET-YOU-WANT-TO-SAVE-TO, | ||
Key: FILE-NAME-YOU-WANT, | ||
Body: res.Body.toString() //res.Body is a buffer so you can call | ||
// "toString()" on it to make it into a string | ||
}; | ||
|
||
s3.putObject(params, (err, res) => { //this will put the file you | ||
// specified in params in the bucket | ||
console.log(err, res); // you'll either get an error or response | ||
// depending on if the file was added to the bucket properly | ||
callback(null, 'Success!'); | ||
}) | ||
}) | ||
|
||
|
||
}; | ||
``` | ||
|
||
Check out the comments in the code to see what it does, and once you understand it, adapt it to your specific needs! | ||
|
||
If you've put all this together, you should have an AWS set up where you can send an email to an address and the body of it is saved to a bucket! | ||
|
||
|
||
### Continuous Integration using Codeship | ||
|
||
After writing your tests, the next step is to set up Continuous Integration (CI) for your Lambda Functions so every time you push up your code to GitHub, the tests are run and the code is deployed to AWS if the tests pass. This example goes through how to set up CI using Codeship. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try to avoid having other tabs in the screenshot as it's "noisy".

(keep the focus on the task you are currently performing to avoid distracting/confusing your reader) 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have access to Photoshop here and the Linux alternatives are a bit of a pain to use. Happy to update this when I get home from my holiday 🍹