EMAIL / LESSON 08
Setting Up Amazon SES.
Verify your domain, set up DKIM and SPF and DMARC, get out of the sandbox, and send your first email from Node

Loading the lesson…
Loading activities…
EMAIL / LESSON 08
Verify your domain, set up DKIM and SPF and DMARC, get out of the sandbox, and send your first email from Node

Loading the lesson…
Loading activities…
This lesson takes you from an empty SES account all the way to a real email sent from your own code. Pick one AWS Region before you start, and do EVERY step in that same Region.
In SES, an identity is something you're allowed to send from. There are two kinds.
You can have both. For a real app, the domain identity is the one you want. The email address identity is handy for quick tests, especially while you're stuck in the sandbox.
Open the SES console. Under Configuration, choose Identities, then Create identity. Select Domain and type in your domain.
If your site lives at www.yourapp.com, enter yourapp.com. AWS warns that including the "www." part makes verification fail.
Leave DKIM signatures enabled and choose Create identity.
SES now shows you three CNAME records under Publish DNS records. Copy them into your domain's DNS settings, wherever your domain is managed.
Copy the record names EXACTLY as shown. The underscore in each name is required, and AWS specifically warns against adding an extra underscore at the start.
If your domain is managed in Amazon Route 53 on the same AWS account, SES can publish these records for you.
AWS says DNS changes "can take up to 72 hours to propagate." As soon as SES finds all three records, the identity status flips to Verified.
Back in Identities, choose Create identity again, select Email address and enter an inbox you can actually open. AWS sends a verification email from no-reply-aws@amazon.com. Click the link inside.
The link expires after 24 hours. If it runs out, use the Resend option on the identity's page.
While you're in the sandbox, every address you send TO has to be verified too, so this test inbox is where your first emails will land.
You met these three in the last chapter. Here's how they fit together in SES, using the descriptions straight from the SES docs.
DKIM adds a digital signature to each message. The three CNAME records you just added are what the SES docs call Easy DKIM. With Easy DKIM, AWS says SES "automatically adds a 2048-bit DKIM key to every email that you send from that identity." You don't have to sign anything in your code.
Every email actually has two senders. The From address is the one people see. The MAIL FROM address is a hidden one used for bounces. By default, SES uses a subdomain of amazonses.com as the MAIL FROM.
To use your own domain there, you set up a custom MAIL FROM domain. Pick a subdomain you don't use for anything else, like bounce.yourapp.com. In the SES console, open your verified domain, find the Custom MAIL FROM domain section, choose Edit and enter that subdomain. SES then shows you two records to add, in these formats.
| Name | Type | Value |
|---|---|---|
| bounce.yourapp.com | MX | 10 feedback-smtp.REGION.amazonses.com |
| bounce.yourapp.com | TXT | "v=spf1 include:amazonses.com ~all" |
REGION will be the code of the Region you're using, such as us-east-1. Copy the exact values the console shows you instead of typing them out. The MAIL FROM domain has to have exactly one MX record, or the setup fails.
DMARC checks that the From address people see actually matches what SPF or DKIM checked. The SES docs explain that a message passes DMARC if either the SPF check or the DKIM check passes with matching domains.
You set DMARC with one TXT record named _dmarc.yourapp.com. The SES docs give this example value.
The p= part is the policy. AWS recommends rolling it out slowly, starting with p=none to only collect reports, then moving to p=quarantine, and finally p=reject once you know your legit mail passes.
Once all your records are in, it's worth running your domain through a checker before you trust it. I built a free email and DNS deliverability checker for exactly this reason, because squinting at TXT records by hand gets old FAST.
Once your domain shows Verified, request production access. In the SES console, open Account dashboard, choose View Get set up page, then Request production access.
Pick Marketing or Transactional, add your website URL and tick the acknowledgement that you only email people who asked for it and that you handle bounces and complaints. AWS gives an initial response within 24 hours.
You can keep building while you wait. Sending to your verified test inbox works the whole time.
Your code needs credentials to call SES. For the SES API those are AWS access keys, which come in two parts, an access key ID and a secret access key.
Here's AWS's guidance, kept short.
Keep the keys out of your code. The AWS SDK reads these environment variables on its own.
Set them in your hosting platform's environment settings. On your own computer, put them in a .env file inside your project folder (the ses-test folder you're about to make), and make sure it never, ever gets committed to git. Node.js doesn't read .env on its own, so you'll point it at the file when you run your code in Step 4.
This example follows the AWS SDK for JavaScript v3 guide, which uses the @aws-sdk/client-ses package and its SendEmailCommand.
The AWS code below uses import lines and a top-level await, so Node.js has to treat your project as an ES module. Following the AWS Get started with Node.js guide, make a new folder, create a package.json, mark the project as a module and install the SES client.
npm pkg set type=module adds "type": "module" to your package.json. Skip it and Node.js reads .js files the old CommonJS way and trips over the very first import line.
You also need a recent Node.js. The AWS SDK for JavaScript v3 README says current versions of the SDK require Node.js 20 or higher. Run node --version to check yours.
Make a libs folder with a file called sesClient.js. This is the AWS example with one change. It reads AWS_REGION from your environment and falls back to us-east-1, where the original hard-codes a Region. Either way, the Region has to be the one where you verified your identities.
Notice there are zero keys in this file. The SDK looks for credentials in a fixed order, and environment variables sit near the front of that line.
Create ses_sendemail.js next to the libs folder. This one's also the AWS example as written.
Swap "recipient@example.com" for your verified test inbox and "sender@example.com" for an address on your verified domain. Then replace the subject and the two body placeholders with real text.
Source is the From address. Html and Text are two versions of the same message, one for email apps that show HTML and one for the ones that only show plain text.
The snippet above defines run but never actually calls it (sneaky, right?). Add this line at the bottom of the file so it runs and prints the result.
Then run the file from inside your ses-test folder. The --env-file flag tells Node.js to load your keys from .env first.
This only works because Step 1 turned the project into an ES module. The import lines and the await sitting outside a function both need it. If you'd rather use require, check out the AWS page on ES6 and CommonJS syntax.
_dmarc. Start with p=none and tighten it slowly.@aws-sdk/client-ses with SendEmailCommand sends your first email in a few dozen lines.Before you send to real users, set up a way to handle bounces and complaints. The SES docs cover using Amazon SNS notifications for exactly that...