From 1a330ba16de137fd6083fa6cc9128ebb7edb0d85 Mon Sep 17 00:00:00 2001 From: David Gatti Date: Mon, 26 Aug 2019 09:18:25 +0200 Subject: [PATCH 1/2] Updated readme Fixed some unclear sentences, and added more examples. --- README.md | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 288e543..d73ba05 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,45 @@ This stack was created out of frustration due to the fact that to this day there The result is an unmanaged email server with unlimited email addresses that also offers the benefit of easily organizing messages by adding the `+` character to the email names. The `+` is converted to a `/`, which correlates to an object path in S3. +### Endless email addresses + +Once you add and confirm your domain with SES, you can put any string you want in front of the `@`, as long as it conforms to the email address standard. This means that you'll have endless email addresses at your disposal, and you'll be able to organize your life in a way never possible before. For example, you can give each service you sign up for its own special email: + +- facebook@example.com +- instagram@example.com +- linkedin@example.com +- etc. + ### Organizing with a + -When you sign up for online services, you can organize your emails with the `+` character in this way: +With that said, you can organize your emails with the `+` character in this way: -- social+facebook@example.com -- social+instagram@example.com -- social+linkedin@example.com +- accounts+social+facebook@example.com +- accounts+social+instagram@example.com +- accounts+social+linkedin@example.com +- accounts+travel+car+hertz@example.com +- accounts+travel+air+jetblue@example.com +- accounts+money+paypal@example.com - etc. -This groups all social emails in the `social` folder. The possibilities are endless. +When dealing with clients we came up with this folder structure: -### Endless email addresses +- clients+company_name+aws+account_name@example.com +- clients+company_name+stripe@example.com +- clients+company_name+sentry@example.com +- clients+company_name+heroku@example.com +- etc. -Once you add and confirm your domain with SES, you can put any string you want in front of the `@`, as long as it conforms to the email address standard. This means that you'll have endless email addresses at your disposal, and you'll be able to organize your life in a way never possible before. For example, you can give each service you sign up for its own special email: +For all sorts of alerts we like to group them like this + +- alarms+company_name+aws+account_name+alarm_type@example.com +- alarms+company_name+sentry+alarm_type@example.com -- facebook@example.com -- instagram@example.com -- linkedin@example.com - etc. -> Basically receive and send email with some skills. +This groups all emails in the corresponding folder by replacing the `+` with a `/` character which creates a folder structure in S3. The possibilities are endless. + +> Basically, receive and send email with some skills. # DISCLAIMER! @@ -65,7 +83,7 @@ The stack is set up in a such a way that any time new code is pushed to a select Keep in mind that when you deploy, everything may not work right out of the box. -### Confirm that you own the domain +### Confirm to SES that you own the domain You have to add your domain and confirm that you own it. Follow these steps to do so: @@ -87,7 +105,7 @@ Deployment creates SES `rule sets`. This should be enabled by default, but it do ### Attach user to the IAM Group -After the stack is deployed you get a IAM Group with the bare minimum policy to allow to access the S3 Bucket with the emails. Use this group to give access to your IAM user to S3 Email. +After the stack is deployed you'll get a IAM Group with a policy attached that will give a user using it the bare minimum to access to the S3-Bucket to read and create emails. # SES Limitations @@ -101,10 +119,10 @@ There are two major limitations with SES: **Receiving email**: 1. An email comes to SES and and it gets stored in `TMP` S3 folder. -1. S3 will trigger the Inbound Lambda Function which will organize the email based on the `to`, `from` and `date` fields. In addition to that, the Lambda will read the domain added to SES, and will use that to determine if the email should land in the `Inbox` or `Sent` folder. If the `to` fields contains the domain from SES, it goes to the `Inbox`, if not, it is assumed the email was sent out. -1. The `Inbox` or `Sent` folder triggers another Lambda function that loads the raw email, converts it to a `.html` and `.txt` file, and stores it alongside the original message. +1. S3 will trigger the Inbound Lambda Function which will organize the email based on the `to`, `from` and `date` fields. In addition to that, the Lambda will read the domain(s) added to SES, and will use that data to determine if the email should land in the `Inbox` or `Sent` folder. If the `to` fields contains the domain from SES, it goes to the `Inbox`, if not, it is assumed the email was sent out. +1. The `Inbox` or `Sent` folder triggers another Lambda function that loads the raw email, converts it to a `.html` and `.txt` file, and stores it alongside the original message, while storing any attachments in the `attachments`. -In addition to this flow, when a new email comes in, a copy of it will be saved in the `Today` folder to show you which emails are new. The S3 bucket has a Life Cycle Policy and will delete any email older than one day from the `Today` folder. This way you always know what is new. +In addition to this flow, when a new email comes in, a copy of it will be saved in the `Today` folder to show you which emails are new. The S3 bucket has a Life Cycle Policy and will delete any email older than one day from the `Today` folder. This way you always know what's new. **Sending email**: From a6a03efed684a4f6f4f9766ac3d9ba002fffd92b Mon Sep 17 00:00:00 2001 From: David Gatti Date: Mon, 26 Aug 2019 09:27:37 +0200 Subject: [PATCH 2/2] Fixed #22 --- 03_Parameters/github_account_name.json | 7 + 03_Parameters/github_token.json | 2 +- .../converter/CodePipeline/pipe_line.json | 2 +- .../Repos/inbound/CodePipeline/pipe_line.json | 2 +- .../outbound/CodePipeline/pipe_line.json | 2 +- CloudFormation.json | 421 +++++++++--------- 6 files changed, 227 insertions(+), 209 deletions(-) create mode 100644 03_Parameters/github_account_name.json diff --git a/03_Parameters/github_account_name.json b/03_Parameters/github_account_name.json new file mode 100644 index 0000000..71beb58 --- /dev/null +++ b/03_Parameters/github_account_name.json @@ -0,0 +1,7 @@ +{ + "ParamGitHubAccountName": { + "Description": "The name of the GitHub account, it is the same names that you find in the URL. Organization or private account.", + "Type": "String", + "Default": "0x4447" + } +} diff --git a/03_Parameters/github_token.json b/03_Parameters/github_token.json index 5fea529..d970881 100644 --- a/03_Parameters/github_token.json +++ b/03_Parameters/github_token.json @@ -1,6 +1,6 @@ { "GitHubToken": { - "Description": "You need to create a Personal access tokens (https://github.com/settings/tokens) for CodePipeline to have access to the GitHub repo despite it being public.", + "Description": "You need to create a Personal access tokens (https://github.com/settings/tokens) for CodePipeline to have access to the GitHub repo even if they are public, and the Scope has to have: repo and admin:repo_hook", "NoEcho": true, "Type": "String" } diff --git a/07_Resources/Repos/converter/CodePipeline/pipe_line.json b/07_Resources/Repos/converter/CodePipeline/pipe_line.json index 7a73681..c8ec76d 100644 --- a/07_Resources/Repos/converter/CodePipeline/pipe_line.json +++ b/07_Resources/Repos/converter/CodePipeline/pipe_line.json @@ -22,7 +22,7 @@ "Version": "1" }, "Configuration": { - "Owner": "0x4447", + "Owner": { "Ref": "ParamGitHubAccountName" }, "Repo": "0x4447-product-s3-email-lambda-converter", "Branch": { "Ref": "Stage" }, "PollForSourceChanges": true, diff --git a/07_Resources/Repos/inbound/CodePipeline/pipe_line.json b/07_Resources/Repos/inbound/CodePipeline/pipe_line.json index 5799712..b609623 100644 --- a/07_Resources/Repos/inbound/CodePipeline/pipe_line.json +++ b/07_Resources/Repos/inbound/CodePipeline/pipe_line.json @@ -22,7 +22,7 @@ "Version": "1" }, "Configuration": { - "Owner": "0x4447", + "Owner": { "Ref": "ParamGitHubAccountName" }, "Repo": "0x4447-product-s3-email-lambda-inbound", "Branch": { "Ref": "Stage" }, "PollForSourceChanges": true, diff --git a/07_Resources/Repos/outbound/CodePipeline/pipe_line.json b/07_Resources/Repos/outbound/CodePipeline/pipe_line.json index 9d67c94..2ae54e4 100644 --- a/07_Resources/Repos/outbound/CodePipeline/pipe_line.json +++ b/07_Resources/Repos/outbound/CodePipeline/pipe_line.json @@ -22,7 +22,7 @@ "Version": "1" }, "Configuration": { - "Owner": "0x4447", + "Owner": { "Ref": "ParamGitHubAccountName" }, "Repo": "0x4447-product-s3-email-lambda-outbound", "Branch": { "Ref": "Stage" }, "PollForSourceChanges": true, diff --git a/CloudFormation.json b/CloudFormation.json index fbc84c2..e369e5a 100644 --- a/CloudFormation.json +++ b/CloudFormation.json @@ -10,8 +10,13 @@ "Description": "The S3 bucket name where CodePipeline will store the artifacts (this is needed only by CP to work, and pass task results to the next stage).", "Type": "String" }, + "ParamGitHubAccountName": { + "Description": "The name of the GitHub account, it is the same names that you find in the URL. Organization or private account.", + "Type": "String", + "Default": "0x4447" + }, "GitHubToken": { - "Description": "You need to create a Personal access tokens (https://github.com/settings/tokens) for CodePipeline to have access to the GitHub repo despite it being public.", + "Description": "You need to create a Personal access tokens (https://github.com/settings/tokens) for CodePipeline to have access to the GitHub repo even if they are public, and the Scope has to have: repo and admin:repo_hook", "NoEcho": true, "Type": "String" }, @@ -281,7 +286,9 @@ "Version": "1" }, "Configuration": { - "Owner": "0x4447", + "Owner": { + "Ref": "ParamGitHubAccountName" + }, "Repo": "0x4447-product-s3-email-lambda-converter", "Branch": { "Ref": "Stage" @@ -327,24 +334,6 @@ ] } }, - "PipelineConverterRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "RoleName": "0x4447_s3_email_codepipeline_converter", - "AssumeRolePolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": "codepipeline.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } - ] - } - } - }, "PipelineConverterPolicy": { "Type": "AWS::IAM::Policy", "Properties": { @@ -501,83 +490,21 @@ } } }, - "S3ConverterPermission": { - "Type": "AWS::Lambda::Permission", - "DependsOn": "LambdaEmailConverter", - "Properties": { - "Action": "lambda:InvokeFunction", - "FunctionName": { - "Ref": "LambdaEmailConverter" - }, - "Principal": "s3.amazonaws.com" - } - }, - "LambdaEmailConverterRole": { + "PipelineConverterRole": { "Type": "AWS::IAM::Role", "Properties": { - "RoleName": "0x4447_s3_email_lambda_converter", + "RoleName": "0x4447_s3_email_codepipeline_converter", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { - "Service": "lambda.amazonaws.com" + "Service": "codepipeline.amazonaws.com" }, "Action": "sts:AssumeRole" } ] - }, - "ManagedPolicyArns": [ - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - ] - } - }, - "LambdaEmailConverter": { - "Type": "AWS::Lambda::Function", - "Description": "This Lambda converts raw emails files in to HTML and TEXT ones.", - "Properties": { - "FunctionName": "0x4447-s3-email-converter", - "Code": { - "ZipFile": "exports.handler = async (event) => {return true;};" - }, - "Handler": "index.handler", - "MemorySize": 128, - "Role": { - "Fn::GetAtt": [ - "LambdaEmailConverterRole", - "Arn" - ] - }, - "Runtime": "nodejs8.10", - "Timeout": 60 - } - }, - "LambdaEmailConverterPolicyS3": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyName": "S3_access", - "Roles": [ - { - "Ref": "LambdaEmailConverterRole" - } - ], - "PolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": "s3:*", - "Resource": [ - { - "Fn::Sub": "arn:aws:s3:::${S3Email}" - }, - { - "Fn::Sub": "arn:aws:s3:::${S3Email}/*" - } - ] - } - ] } } }, @@ -665,6 +592,29 @@ } } }, + "CodeBuildConverterPolicyS3": { + "Type": "AWS::IAM::Policy", + "Properties": { + "Roles": [ + { + "Ref": "CodeBuildConverterRole" + } + ], + "PolicyName": "s3_access", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:*", + "Resource": { + "Fn::Sub": "arn:aws:s3:::${CodePipelineBucketName}/*" + } + } + ] + } + } + }, "CodeBuildConverterPolicyLambdaUpdate": { "Type": "AWS::IAM::Policy", "Properties": { @@ -688,33 +638,90 @@ } } }, - "CodeBuildConverterPolicyS3": { + "LambdaEmailConverter": { + "Type": "AWS::Lambda::Function", + "Description": "This Lambda converts raw emails files in to HTML and TEXT ones.", + "Properties": { + "FunctionName": "0x4447-s3-email-converter", + "Code": { + "ZipFile": "exports.handler = async (event) => {return true;};" + }, + "Handler": "index.handler", + "MemorySize": 256, + "Role": { + "Fn::GetAtt": [ + "LambdaEmailConverterRole", + "Arn" + ] + }, + "Runtime": "nodejs8.10", + "Timeout": 60 + } + }, + "S3ConverterPermission": { + "Type": "AWS::Lambda::Permission", + "DependsOn": "LambdaEmailConverter", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "LambdaEmailConverter" + }, + "Principal": "s3.amazonaws.com" + } + }, + "LambdaEmailConverterRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": "0x4447_s3_email_lambda_converter", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + }, + "ManagedPolicyArns": [ + "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + } + }, + "LambdaEmailConverterPolicyS3": { "Type": "AWS::IAM::Policy", "Properties": { + "PolicyName": "S3_access", "Roles": [ { - "Ref": "CodeBuildConverterRole" + "Ref": "LambdaEmailConverterRole" } ], - "PolicyName": "s3_access", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", - "Resource": { - "Fn::Sub": "arn:aws:s3:::${CodePipelineBucketName}/*" - } + "Resource": [ + { + "Fn::Sub": "arn:aws:s3:::${S3Email}" + }, + { + "Fn::Sub": "arn:aws:s3:::${S3Email}/*" + } + ] } ] } } }, - "PipelineInbound": { + "PipelineOutbound": { "Type": "AWS::CodePipeline::Pipeline", "Properties": { - "Name": "0x4447_s3_email_lambda_inbound", + "Name": "0x4447_s3_email_lambda_outbound", "ArtifactStore": { "Location": { "Ref": "CodePipelineBucketName" @@ -723,7 +730,7 @@ }, "RoleArn": { "Fn::GetAtt": [ - "PipelineInboundRole", + "PipelineOutboundRole", "Arn" ] }, @@ -741,8 +748,10 @@ "Version": "1" }, "Configuration": { - "Owner": "0x4447", - "Repo": "0x4447-product-s3-email-lambda-inbound", + "Owner": { + "Ref": "ParamGitHubAccountName" + }, + "Repo": "0x4447-product-s3-email-lambda-outbound", "Branch": { "Ref": "Stage" }, @@ -772,7 +781,7 @@ ], "Configuration": { "ProjectName": { - "Ref": "CodeBuildInbound" + "Ref": "CodeBuildOutbound" } }, "ActionTypeId": { @@ -787,13 +796,13 @@ ] } }, - "PipelineInboundPolicy": { + "PipelineOutboundPolicy": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyName": "default", "Roles": [ { - "Ref": "PipelineInboundRole" + "Ref": "PipelineOutboundRole" } ], "PolicyDocument": { @@ -943,10 +952,10 @@ } } }, - "PipelineInboundRole": { + "PipelineOutboundRole": { "Type": "AWS::IAM::Role", "Properties": { - "RoleName": "0x4447_s3_email_codepipeline_inbound", + "RoleName": "0x4447_s3_email_codepipeline_outbound", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -961,13 +970,13 @@ } } }, - "CodeBuildInbound": { + "CodeBuildOutbound": { "Type": "AWS::CodeBuild::Project", "Properties": { - "Name": "0x4447_s3_email_inbound", + "Name": "0x4447_s3_email_outbound", "ServiceRole": { "Fn::GetAtt": [ - "CodeBuildInboundRole", + "CodeBuildOutboundRole", "Arn" ] }, @@ -988,17 +997,17 @@ "Name": "FUNCTION_NAME", "Type": "PLAINTEXT", "Value": { - "Ref": "LambdaEmailInbound" + "Ref": "LambdaEmailOutbound" } } ] } } }, - "CodeBuildInboundRole": { + "CodeBuildOutboundRole": { "Type": "AWS::IAM::Role", "Properties": { - "RoleName": "0x4447_s3_email_codebuild_inbound", + "RoleName": "0x4447_s3_email_codebuild_outbound", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -1013,12 +1022,12 @@ } } }, - "CodeBuildDeployPolicyCWL": { + "CodeBuildOutboundPolicyCWL": { "Type": "AWS::IAM::Policy", "Properties": { "Roles": [ { - "Ref": "CodeBuildInboundRole" + "Ref": "CodeBuildOutboundRole" } ], "PolicyName": "cloud_watch_log_access", @@ -1034,10 +1043,10 @@ ], "Resource": [ { - "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_inbound" + "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_outbound" }, { - "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_inbound:*" + "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_outbound:*" } ] } @@ -1045,12 +1054,12 @@ } } }, - "CodeBuildDeployPolicyS3": { + "CodeBuildOutboundPolicyS3": { "Type": "AWS::IAM::Policy", "Properties": { "Roles": [ { - "Ref": "CodeBuildInboundRole" + "Ref": "CodeBuildOutboundRole" } ], "PolicyName": "s3_access", @@ -1068,12 +1077,12 @@ } } }, - "CodeBuildDeployPolicyLambdaUpdate": { + "CodeBuildOutboundPolicyLambdaUpdate": { "Type": "AWS::IAM::Policy", "Properties": { "Roles": [ { - "Ref": "CodeBuildInboundRole" + "Ref": "CodeBuildOutboundRole" } ], "PolicyName": "update_lambda_code", @@ -1084,26 +1093,26 @@ "Effect": "Allow", "Action": "lambda:UpdateFunctionCode", "Resource": { - "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaEmailInbound}" + "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaEmailOutbound}" } } ] } } }, - "LambdaEmailInbound": { + "LambdaEmailOutbound": { "Type": "AWS::Lambda::Function", - "Description": "This Lambda organizes all the incoming emails based on the From and To field.", + "Description": "Take the JSON and convert it in to an raw email.", "Properties": { - "FunctionName": "0x4447-s3-email-inbound", + "FunctionName": "0x4447-s3-email-outbound", "Code": { "ZipFile": "exports.handler = async (event) => {return true;};" }, "Handler": "index.handler", - "MemorySize": 128, + "MemorySize": 256, "Role": { "Fn::GetAtt": [ - "LambdaEmailInboundRole", + "LambdaEmailOutboundRole", "Arn" ] }, @@ -1118,10 +1127,21 @@ } } }, - "LambdaEmailInboundRole": { + "S3OutboundPermission": { + "Type": "AWS::Lambda::Permission", + "DependsOn": "LambdaEmailOutbound", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "LambdaEmailOutbound" + }, + "Principal": "s3.amazonaws.com" + } + }, + "LambdaEmailOutboundRole": { "Type": "AWS::IAM::Role", "Properties": { - "RoleName": "0x4447_s3_email_lambda_inbound", + "RoleName": "0x4447_s3_email_lambda_outbound", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -1139,24 +1159,13 @@ ] } }, - "S3InboundPermission": { - "Type": "AWS::Lambda::Permission", - "DependsOn": "LambdaEmailInbound", - "Properties": { - "Action": "lambda:InvokeFunction", - "FunctionName": { - "Ref": "LambdaEmailInbound" - }, - "Principal": "s3.amazonaws.com" - } - }, - "LambdaEmailInboundPolicyS3": { + "LambdaEmailOutboundPolicyS3": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyName": "S3_access", "Roles": [ { - "Ref": "LambdaEmailInboundRole" + "Ref": "LambdaEmailOutboundRole" } ], "PolicyDocument": { @@ -1178,13 +1187,13 @@ } } }, - "LambdaEmailInboundPolicySES": { + "LambdaEmailOutboundPolicySES": { "Type": "AWS::IAM::Policy", "Properties": { - "PolicyName": "ses_access", + "PolicyName": "ses", "Roles": [ { - "Ref": "LambdaEmailInboundRole" + "Ref": "LambdaEmailOutboundRole" } ], "PolicyDocument": { @@ -1192,17 +1201,17 @@ "Statement": [ { "Effect": "Allow", - "Action": "ses:ListIdentities", + "Action": "ses:SendRawEmail", "Resource": "*" } ] } } }, - "PipelineOutbound": { + "PipelineInbound": { "Type": "AWS::CodePipeline::Pipeline", "Properties": { - "Name": "0x4447_s3_email_lambda_outbound", + "Name": "0x4447_s3_email_lambda_inbound", "ArtifactStore": { "Location": { "Ref": "CodePipelineBucketName" @@ -1211,7 +1220,7 @@ }, "RoleArn": { "Fn::GetAtt": [ - "PipelineOutboundRole", + "PipelineInboundRole", "Arn" ] }, @@ -1229,8 +1238,10 @@ "Version": "1" }, "Configuration": { - "Owner": "0x4447", - "Repo": "0x4447-product-s3-email-lambda-outbound", + "Owner": { + "Ref": "ParamGitHubAccountName" + }, + "Repo": "0x4447-product-s3-email-lambda-inbound", "Branch": { "Ref": "Stage" }, @@ -1260,7 +1271,7 @@ ], "Configuration": { "ProjectName": { - "Ref": "CodeBuildOutbound" + "Ref": "CodeBuildInbound" } }, "ActionTypeId": { @@ -1275,13 +1286,13 @@ ] } }, - "PipelineOutboundPolicy": { + "PipelineInboundPolicy": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyName": "default", "Roles": [ { - "Ref": "PipelineOutboundRole" + "Ref": "PipelineInboundRole" } ], "PolicyDocument": { @@ -1431,10 +1442,10 @@ } } }, - "PipelineOutboundRole": { + "PipelineInboundRole": { "Type": "AWS::IAM::Role", "Properties": { - "RoleName": "0x4447_s3_email_codepipeline_outbound", + "RoleName": "0x4447_s3_email_codepipeline_inbound", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -1449,31 +1460,13 @@ } } }, - "CodeBuildOutboundRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "RoleName": "0x4447_s3_email_codebuild_outbound", - "AssumeRolePolicyDocument": { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": "codebuild.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } - ] - } - } - }, - "CodeBuildOutbound": { + "CodeBuildInbound": { "Type": "AWS::CodeBuild::Project", "Properties": { - "Name": "0x4447_s3_email_outbound", + "Name": "0x4447_s3_email_inbound", "ServiceRole": { "Fn::GetAtt": [ - "CodeBuildOutboundRole", + "CodeBuildInboundRole", "Arn" ] }, @@ -1494,19 +1487,37 @@ "Name": "FUNCTION_NAME", "Type": "PLAINTEXT", "Value": { - "Ref": "LambdaEmailOutbound" + "Ref": "LambdaEmailInbound" } } ] } } }, - "CodeBuildOutboundPolicyCWL": { + "CodeBuildInboundRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "RoleName": "0x4447_s3_email_codebuild_inbound", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "codebuild.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + } + } + }, + "CodeBuildDeployPolicyCWL": { "Type": "AWS::IAM::Policy", "Properties": { "Roles": [ { - "Ref": "CodeBuildOutboundRole" + "Ref": "CodeBuildInboundRole" } ], "PolicyName": "cloud_watch_log_access", @@ -1522,10 +1533,10 @@ ], "Resource": [ { - "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_outbound" + "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_inbound" }, { - "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_outbound:*" + "Fn::Sub": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/0x4447_s3_email_inbound:*" } ] } @@ -1533,12 +1544,12 @@ } } }, - "CodeBuildOutboundPolicyS3": { + "CodeBuildDeployPolicyS3": { "Type": "AWS::IAM::Policy", "Properties": { "Roles": [ { - "Ref": "CodeBuildOutboundRole" + "Ref": "CodeBuildInboundRole" } ], "PolicyName": "s3_access", @@ -1556,12 +1567,12 @@ } } }, - "CodeBuildOutboundPolicyLambdaUpdate": { + "CodeBuildDeployPolicyLambdaUpdate": { "Type": "AWS::IAM::Policy", "Properties": { "Roles": [ { - "Ref": "CodeBuildOutboundRole" + "Ref": "CodeBuildInboundRole" } ], "PolicyName": "update_lambda_code", @@ -1572,26 +1583,26 @@ "Effect": "Allow", "Action": "lambda:UpdateFunctionCode", "Resource": { - "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaEmailOutbound}" + "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaEmailInbound}" } } ] } } }, - "LambdaEmailOutbound": { + "LambdaEmailInbound": { "Type": "AWS::Lambda::Function", - "Description": "Take the JSON and convert it in to an raw email.", + "Description": "This Lambda organizes all the incoming emails based on the From and To field.", "Properties": { - "FunctionName": "0x4447-s3-email-outbound", + "FunctionName": "0x4447-s3-email-inbound", "Code": { "ZipFile": "exports.handler = async (event) => {return true;};" }, "Handler": "index.handler", - "MemorySize": 128, + "MemorySize": 256, "Role": { "Fn::GetAtt": [ - "LambdaEmailOutboundRole", + "LambdaEmailInboundRole", "Arn" ] }, @@ -1606,10 +1617,21 @@ } } }, - "LambdaEmailOutboundRole": { + "S3InboundPermission": { + "Type": "AWS::Lambda::Permission", + "DependsOn": "LambdaEmailInbound", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Ref": "LambdaEmailInbound" + }, + "Principal": "s3.amazonaws.com" + } + }, + "LambdaEmailInboundRole": { "Type": "AWS::IAM::Role", "Properties": { - "RoleName": "0x4447_s3_email_lambda_outbound", + "RoleName": "0x4447_s3_email_lambda_inbound", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ @@ -1627,24 +1649,13 @@ ] } }, - "S3OutboundPermission": { - "Type": "AWS::Lambda::Permission", - "DependsOn": "LambdaEmailOutbound", - "Properties": { - "Action": "lambda:InvokeFunction", - "FunctionName": { - "Ref": "LambdaEmailOutbound" - }, - "Principal": "s3.amazonaws.com" - } - }, - "LambdaEmailOutboundPolicyS3": { + "LambdaEmailInboundPolicyS3": { "Type": "AWS::IAM::Policy", "Properties": { "PolicyName": "S3_access", "Roles": [ { - "Ref": "LambdaEmailOutboundRole" + "Ref": "LambdaEmailInboundRole" } ], "PolicyDocument": { @@ -1666,13 +1677,13 @@ } } }, - "LambdaEmailOutboundPolicySES": { + "LambdaEmailInboundPolicySES": { "Type": "AWS::IAM::Policy", "Properties": { - "PolicyName": "ses", + "PolicyName": "ses_access", "Roles": [ { - "Ref": "LambdaEmailOutboundRole" + "Ref": "LambdaEmailInboundRole" } ], "PolicyDocument": { @@ -1680,7 +1691,7 @@ "Statement": [ { "Effect": "Allow", - "Action": "ses:SendRawEmail", + "Action": "ses:ListIdentities", "Resource": "*" } ]