Serverless sending and receiving e-mails using AWS is not fun in my opinion. AWS offers Simple Email Service (SES) to achieve this. But the UI and also Infrastructure as Code (IaC) support is lacking. You often need to manually change settings which is error prone. When I recently built another landing page for myself, I was repeating the same steps as for the previous page. It bothered me why there’s no easy automation that’s doing it for me. This is what I’m presenting to you today: My first AWS CDK Constructs to send and receive e-mails.
You can find the source code of the AWS CDK Constructs in the ses-email-forwarding GitHub repository. Besides that, I also made ses-verify-identities available as separate AWS CDK Constructs.
Setup Steps With AWS SES
Have you ever built your own landing page with its own domain? Or have you ever wanted to use another alias for receiving e-mails? Or did you just want to use an e-mail address for a domain you own without the hassle of setting up your own mail server and instead forward the mails to your existing inbox? If yes, I have some great news for you! 😊 Initially, I have used a library called aws-lambda-ses-forwarder for serverless sending and receiving e-mails. I always had to follow these manual steps:
- Setup AWS SES and verify my domain.
- Configure receipt rules for the different e-mail addresses.
- Then setup a Lambda function SES Action that forwards all my e-mails from SES to a Gmail address.
- Configure SMTP for AWS SES and setup Gmail to send e-mails with my verified domain.
My new AWS CDK constructs below automate the first three setup steps for AWS SES. They even allow you to automatically verify your e-mail addresses or domains within SES (if you’re using Route53). Just deploy the constructs in your AWS CDK stack and you’re ready to go. You only need to create SMTP credentials for AWS SES and setup your settings with Gmail (or other providers). Let’s see how it’s working ⬇️
AWS CDK Constructs to the Rescue
The best way to show how it’s working is by showing you a few lines of code:
new EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {
enableRuleSet: true,
emailForwardingProps: [{
domainName: 'example.org',
verifyDomain: true,
fromPrefix: 'noreply',
emailMappings: [{
receivePrefix: 'hello',
targetEmails: ['[email protected]']
}]
}]
});
The code is using the EmailForwardingRuleSet
construct to configure everything. Let me quickly the most important things:
- You can configure to automatically enable the rule set because you can only have on active rule set in AWS SES.
- You define e-mail forwarding rules by specifying your domain name and the e-mail mappings. E-mail mappings define a
receivePrefix
which is your e-mail alias and a list oftargetEmails
. All e-mails to your alias/prefix are forwarded to these target e-mails. The forwarded e-mails have a prefix of[email protected]
. - If the domain is managed by Route53, then you can automatically verify the domain. This setting will configure some custom resources to validate the domains.
That’s it already. You can further extend the configuration of course. For example, you can add more e-mail mappings for various aliases/prefixes. Or you can add another domain with individual e-mail mappings. It’s up to you 👍
[mailjet_subscribe widget_id=”3″]
Deploy Your AWS CDK Stack
Now you just need to put everything into an AWS CDK stack. Before you start, initialize a new CDK stack and install my CDK constructs:
cdk init app --language=typescript
npm i -D @seeebiii/ses-email-forwarding
Then, create a new file that contains your stack. It can look similar to the following example:
const app = new cdk.App();
class EmailForwardingSetupStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {
// define your config here
});
}
}
new EmailForwardingSetupStack(app, 'EmailForwardingSetupStack', {
env: {
account: '<account-id>',
region: '<region>'
}
});
Finally, you use the cdk deploy
command to deploy the stack. Everything else like verifying your domains and setting up SES will be done for you. Now you can start with serverless sending and receiving e-mails!
In the end, you’ll have this architecture for serverless receiving e-mails using AWS SES:
All 1.) incoming e-mails are handled by SES. SES will 2.) move them to S3 and afterwards 3.) invokes a Lambda function. This Lambda function 4.) loads the e-mail from S3 and 5.) forwards it to either Gmail or another target e-mail address. In case you are interested, I have written another blog post about how you can include AWS Lambda functions inside a CDK construct.
Sending E-Mails with AWS SES
Unfortunately this is the remaining step that can’t be automated. Once the above CDK stack is deployed to your AWS Account, you need to create SMTP credentials in AWS SES. These credentials allow you to send e-mails from any e-mail application or provider like Gmail. However, this will only work if you have verified your sender domain in AWS SES. Otherwise your e-mails will only be sent to verified e-mail addresses to avoid that you’re sending spam through AWS SES. If you would like to verify the target e-mail addresses with the CDK construct, just use the setting verifyTargetEmailAddresses
.
Other Solutions
You may have already asked yourself if there are really no other existing solutions to this problem. I can assure you there are other solutions for sending and receiving e-mails in a serverless way. However, they did not solve my problem as I expected or I’ve discovered them too late. Here are a few alternatives now:
- aws-lambda-ses-forwarder -> An NPM package to be used in a Lambda function. It can be triggered by an SES event and forwards e-mails to e.g. Gmail. Unfortunately, only using this library in a Lambda function requires you to setup all the necessary steps by hand. Besides that it offers a really flexible configuration for forwarding e-mails.
- aws-cfn-ses-domain -> CloudFormation custom resources for domain and e-mail verification. This helps if you’re writing your infrastructure in CloudFormation but it’s missing some other pieces, like e-mail handling in general.
- S3 Email -> A combination of S3 and SES where e-mails are stored on S3 and S3 is used as the “e-mail interface”.
- simplelogin.io -> An SaaS app to setup various e-mail aliases. You can also deploy it yourself on AWS and connect the stack with SES. It’s probably the most user friendly way to solve the user cases I’ve mentioned above. However, I only discovered it after I had implemented most of the things. Also, the self-hosting steps looked like too much work is necessary.
- improvmx.com -> An SaaS app similar to simplelogin.io. It can create e-mail aliases for you and forward the e-mails to another address like Gmail. It’s pretty similar to what my CDK constructs can do for you. Like the other one, I only discovered this solution after I had implemented most of the things. Unfortunately, there’s no self-hosting version available as far as I know.
Conclusion
I’ve learned a lot on the way of building my first AWS CDK construct! On tricky part was to bundle a Lambda function inside the AWS CDK Construct as mentioned above. I’m really happy with the result because I can easily extend the settings for new landing pages or other email aliases. What do you think about my solution? Let me know in the comments below or mention me on Twitter!