When working with certain domains there may not be a requirement to have a full blown email system running but there may be a requirement to forward emails to another system and therefore it is important to have a reliable, functional, serverless and ideally free or very minimal cost email system available. I use this for my own purpose to verify infra.engineer via email for proof of ownership for the SSL Certificate and renewal emails without having to have a full blown dedicated mailbox attached to the domain.

This guide utilises AWS SES and Lambda, building a mail system that integrates seamlessly with your Gmail account, at the same time allowing you to send and receive mail from multiple mailboxes within your own domain, although this guide focuses on Gmail other email systems can be used such as Office365 and iCloud Mail.

Flow

The workflow of this is as follows;

  • An email is sent to an address on your domain that is picked up by SES
  • SES writes the email to your S3 bucket
  • SES notifies Lambda that an email has arrived
  • Lambda reads the email from S3 and forwards it onto the designated Gmail account

Create DNS zone for your domain on Amazon Route 53

Skip this step if your DNS Zone already sits within Route 53.

The first step is to create a Public Hosted Zone for your domain on Amazon Route 53. To do this, access to AWS console and go to Route 53 -> Hosted zones -> Create Hosted Zone.

Verify the domain on AWS SES

Search for Simple Email Service within the AWS Management Console.

Make sure you are in the correct Region from which you are enabling SES email

Click on the 'Domains' link in the left navigation

Add the domain from which you will be sending emails (i.e. infra.engineer)

Once you add the domain, Amazon will ask you to create certain valued DNS records to verify you are authorised to send email on behalf of the domain.

These records will have to be added to your domain's control panel for verification, if is recommended to add the DKIM records

Add these DNS records into your DNS Zone created earlier using the management console, below is an example of adding the records into AWS Route 53

 

Create an MX record depending on your SES Receiving Endpoint using the MX record given earlier by AWS. This is important to ensure mail hits SES.

For SES Endpoints see list at https://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html#region-endpoints 

When AWS has confirmed that these values are present in the DNS settings for the domain, the Status for the domain will change to "verified".

This may take up to 72 hours with certain companies but if you are using AWS Route 53 (Highly recommended) these should be verified in under 10 minutes.

 

Create an S3 Bucket and apply policy

Within AWS S3, create a bucket, in this guide i have created a bucket called infra.engineer.mailbox

Once the bucket is created, go to Permissions > Bucket Policy and paste the snippet below changing the S3 bucket name within resource and your ARN number within the Referrer section, save it ensuring no validation errors.

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Sid": "AllowSESPuts",
         "Effect": "Allow",
         "Principal": {
             "Service": "ses.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<s3 bucket name>/*",
      "Condition": {
         "StringEquals": {
            "aws:Referer": "<ARN Number with no hypens or spaces>"
         }
      }
   }
  ]
}

Create a Lambda function to forward incoming mail to Gmail

Open up the Amazon Lambda service and click Create function

Add a name (i.e. SendToGmail) and role, set the runtime to Node.js 10.x

Follow the set up instructions from https://github.com/arithmetric/aws-lambda-ses-forwarder utilising the index.js file

This github script is a Node.js script for AWS Lambda that uses the inbound/outbound capabilities of AWS Simple Email Service (SES) to run a "serverless" email forwarding service.

 The key section to change within the index.js is the following;

 

var defaultConfig = {
  fromEmail: "This email address is being protected from spambots. You need JavaScript enabled to view it.",
  subjectPrefix: "Lambda/SES",
  emailBucket: "s3 bucket name",
  emailKeyPrefix: "email/",
  forwardMapping: {
    "This email address is being protected from spambots. You need JavaScript enabled to view it.": [
      "This email address is being protected from spambots. You need JavaScript enabled to view it."
    ],
    "@infra.engineer": [
      "This email address is being protected from spambots. You need JavaScript enabled to view it."
    ]
  }
};

The timeout can be increased to 20 or 30 seconds if issues are experienced although mine works fine on 5 seconds.

Create a new rule for received emails

Within SES, go to Email Receiving > Rule Sets and Create Rule

Add the full domain of the website under recipient, if you prefer to look it down rather than using a catch all, add the email address here

Create an S3 and Lambda action, the S3 bucket can be created under the drop down section, reference the Lambda function that was created earlier;

Give the rule a logical name

Review the receipt rule and create rule

You may get a missing permissions prompt for the lambda function which you will need to add, i.e.

Verify your Gmail address and create SMTP user

In order for Amazon SES to accept outgoing mail from your Gmail account it is necessary to verify your email address and create an SMTP user.

Within SES, click the "SMTP Settings" link in the left navigation, and note the SMTP host and port.

Click on the "Create my SMTP credentials" button. Follow on-screen instructions to create a logically named IAM SMTP username and password. Download your SMTP credentials and store in a safe place.

In the sandbox environment, you will also have to verify an email address in which mail will be sent to, select Email Addresses then verify a new email address

Finally if required, you will need to tell Amazon that you are ready to take it out of the sandbox (which limits SES to 200 emails per day and where you need to verify each recipient email address) by submitting a support ticket to raise your sending limit following these instructions. https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html

You should now be able to test by sending an email address to something@yourdomain which should now forward to your gmail account. You should also see the email in your S3 bucket providing everything is working.

Configure Gmail to send email from your domain’s addresses (If required)

Finally, configure Gmail to send mail by putting your domain’s address as sender.

Login to Gmail > Settings > Accounts and Import > Send Email As

Add the send from account you wish to use (The pre-populated name is the inbound and needs to be chance to your SMTP endpoint depending on your region shown in the table below) then add the SES SMTP username and password, you will then be emailed to your gmail account a link with a code for verification, this needs to be added to complete the setup. You should now be able to change the from field when replying to emails from your site.



In order to receive mail nothing else should be required as SES should take care of it.

Issues

If your email is not being received you can troubleshoot it by looking at the error code of the bounce back email, using the Cloudwatch Lamda monitoring and the SES logs which should shed light on where the problem lies.