hosting email for close to free on aws ses

5 min read Original article ↗

Anyone who knows me knows how cheap I am, especially when it comes to paying for services I feel I can run myself. Email is no exception. I've used Gmail since it was invite-only beta, but I've always wanted to have email that was untethered from the big email hosting companies out there. In the past I attempted to run a mail server through a terrible VPS provider and though I got it all working, I was burned when the VPS hosting company suddenly went under in the middle of the night.

This brings us to the present. When I started this blog, I wanted to host my own email in some fashion without just forwarding my domain specific email to a Gmail address. In this post we are going to go over a setup I put together over the course of a few hours that allows me to host mail in the cloud nearly for free.

Overview

This setup is surprisingly simple yet very flexible. To get this up and running you'll need to set up the following:

  • AWS Simple Email Service (SES)
  • AWS S3 Bucket
  • Linux Server with Python3 and Dovecot (an IMAP server) installed
  • A TLS certificate (LetsEncrypt is a great option)

The Linux server in this setup can be hosted in the cloud or a home server. Most ISPs don't block the ports required to run an IMAP server at home (you could also use a non-standard port). Many ISPs also have extremely long leases on IP addresses. If you want something more stable though, a cloud hosted instance might be a better option. That being said, AWS does provide a free-tier EC2 option that should be able to handle a Dovecot install.

AWS SES

AWS SES is designed for programatically sending marketing blasts and transactional email. There are a few interesting features that make it work well for personal email as well. Setting up SES is pretty simple:

  • Navigate to Simple Email Service in the AWS Console
  • The first thing you need to do is verify that you own the domain you want to configure email for, this is done under Identity Mangement
  • TIP Verify the domain! All through the documentation they really push for validating specific "From" addresses. If you just verify the whole domain, you don't have to validate specific addresses
  • To start the process, click on "Verify a New Domain"
  • In the window that follows, make sure to check the box to generate DKIM settings
  • Click on Verify This Domain to continue
  • You'll be presented with a screen that lists a number of DNS records you need to add to your domain.
  • After adding these records, your domain should eventually show as verified under both Verification Status and DKIM Status

At this point, your domain is ready to send email. In the next section we'll go through what needs to happen to set up your first email address.

Before we get an email account set up, we also need to configure SMTP via SES. This is what allows you to send mail from your domain via an email client. To get this configured:

  • Click on SMTP Settings in the SES Dashboard
  • Click on Create My SMTP Credentials and follow the prompts

At the end, it will give you the details you need to connect your mail client to SES.

TIP For further compatibility, I would recommend setting up a custom MAIL FROM domain. You can configure this setting via the Domains option from the SES Dashboard. In my case I set up a sub-domain of mail and used it as my FROM domain. When you configure this it will give you a new MX record to add to your domain as well as an SPF record that is used by email servers to validate that your email came from the correct domain.

AWS SES to S3

One option you have with SES is to send all incoming mail to a specific S3 bucket. This is a super flexible option. Once the files are in S3, you can process them any way you see fit. In my bucket I have a processed directory where I move mail that I have already processed on my local IMAP server.

Check out the AWS Documentation on setting up SES to forward to an S3 bucket here.

TIP Set up a lifecycle policy on your S3 bucket to remove files older than 30 days. This will keep costs down and will also speed up mail retrieval by the Python script later in this post.

Dovecot

Next, we will set up an IMAP server to serve our mail for consumption by an email client. This is pretty dead simple. I do recommend getting a TLS cert for your domain. The best way to do this is to use the DNS verification method of the Let's Encrypt cert generation process. You can read more about that here. In order for this cert to work you'll also need to make sure to set up a DNS A record for your home server. I personally created an A Record to point the imap subdomain to my home IP address and created the cert for that subdomain as well.

I am not going to cover how to install Dovecot — it should be in your distribution's package manager — but I will provide my configuration file:

mail_home=/var/mail/%n
mail_location = mbox:~/mail:INBOX=/var/mail/%u

# if you want to use system users
passdb {
driver = pam
}

userdb {
driver = passwd
args = blocking=no
}

ssl=yes
ssl_cert=