DEV Community

Cover image for Serverless Sending and Receiving E-Mails, the CDK Way
Sebastian Hesse
Sebastian Hesse

Posted on • Originally published at sebastianhesse.de on

Serverless Sending and Receiving E-Mails, the CDK Way

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:

  1. Setup AWS SES and verify my domain.
  2. Configure receipt rules for the different e-mail addresses.
  3. Then setup a Lambda function SES Action that forwards all my e-mails from SES to a Gmail address.
  4. 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: ['whatever+hello@provider.com']
    }]
  }]
});
Enter fullscreen mode Exit fullscreen mode

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 of targetEmails. All e-mails to your alias/prefix are forwarded to these target e-mails. The forwarded e-mails have a prefix of noreply@example.org.
  • 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 👍

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
Enter fullscreen mode Exit fullscreen mode

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>'
  }
});
Enter fullscreen mode Exit fullscreen mode

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:

Architecture how an email is received and forwarded in a serverless way.

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!

The post Serverless Sending and Receiving E-Mails, the CDK Way was first published on Sebastian Hesse - Software Engineer.

Top comments (0)