Configuring SPF, DKIM, and DMARC for AWS SES with Terraform

Bjorn Krols

Bjorn Krols

Published on
27 December 2021

In this article you will learn how to configure SPF, DKIM, and DMARC ,the three pillars of email authentication, for AWS SES with Terraform.

Prerequisites

  • You use Route 53 to manage your email domain.
  • You have created an SES domain identity resource for your email domain.
  • You have basic knowledge of Terraform.
  • You have basic knowledge of DNS.

DNS

All three methods heavily rely on DNS (mostly via TXT records).

For each method you will add at least one record to your DNS configuration:

  • SPF record: A list of authorized domains for sending messages.
  • DKIM record: A cryptographic public key.
  • DMARC record: Instructions on how to handle unauthenticated mail.

Email providers constantly check these records.

SPF

Sender Policy Framework

An SPF record indicates which domains are authorized for sending messages.

Email providers use this information to determine whether a message comes from a verified source.

The domain name for AWS SES is amazonses.com.

resource "aws_route53_record" "route_53_root_txt" {
  zone_id = aws_route53_zone.hosted_zone.id
  name    = ""
  type    = "TXT"
  ttl     = "300"
  records = [
    "v=spf1 include:amazonses.com -all"
  ]
}
  • v=spf1: Indicates the SPF record version.
  • include:amazonses.com: Allows the specified domain.
  • -all: Should always go at the end of the SPF record.

You cannot have multiple SPF records for a single domain, but you can specify multiple domains inside one record.

resource "aws_route53_record" "route_53_root_txt" {
  zone_id = aws_route53_zone.hosted_zone.id
  name    = ""
  type    = "TXT"
  ttl     = "300"
  records = [
    "v=spf1 include:amazonses.com include:_spf.google.com -all"
  ]
}

To verify your configuration, enter your domain name here.

DKIM

DomainKeys Identified Mail

DKIM is a standard that allows senders to sign their email messages with a cryptographic key.

An email message that is sent using DKIM includes a DKIM-Signature header field that contains a cryptographically signed representation of the message.

An email provider that receives the message can use a public key, published as a DNS record, to decode the signature.

Email providers use this information to determine whether a message is authentic.

resource "aws_ses_domain_identity" "email_domain_identity" {
  domain = var.email_domain_name
}

resource "aws_ses_domain_dkim" "email_dkim" {
  domain = aws_ses_domain_identity.email_domain_identity.domain
}

resource "aws_route53_record" "email_dkim_records" {
  count   = 3
  zone_id = var.hosted_zone_id
  name    = "${element(aws_ses_domain_dkim.email_dkim.dkim_tokens, count.index)}._domainkey.${var.email_domain_name}"
  type    = "CNAME"
  ttl     = "300"
  records = [
    "${element(aws_ses_domain_dkim.email_dkim.dkim_tokens, count.index)}.dkim.amazonses.com",
  ]
}

The records that SES creates are CNAME instead of TXT records so that SES can host the signing keys. By hosting the signing keys, SES can automatically rotate signing credentials and mitigate the risk of any key leak.

You can have multiple DKIM records on a single domain.

To verify your configuration, enter the full record names (xxxxxxx._domainkey.domain.com) in the domain input here. Only a single record will be valid, this is because of the rotation system mentioned above.

DMARC

Domain-based Message Authentication, Reporting and Conformance

The DMARC record contains instructions for email providers on how to handle unauthenticated mail.

You can use the record to specify:

  • Which mechanism (DKIM, SPF or both) to employ.
  • How the receiver should deal with failures.
  • Where to send reports to.

You must not have multiple DMARC records for a single domain,

resource "aws_route53_record" "route_53_dmarc_txt" {
  zone_id = aws_route53_zone.hosted_zone.id
  name    = "_dmarc.${var.email_domain_name}"
  type    = "TXT"
  ttl     = "300"
  records = [
    "v=DMARC1;p=quarantine;pct=75;rua=mailto:engineering@example.org"
  ]
}
  • v=DMARC1: Identifies the record retrieved as a DMARC record. It must be the first tag in the list.
  • p=quarantine: Policy to apply to email that fails the DMARC test.
  • pct=75: Percentage of messages to which the DMARC policy is to be applied.
  • mailto:engineering@example.org: Comma-separated addresses to which aggregate feedback is to be sent.

There are three DMARC policies which can be included in your DMARC record:

  1. Monitor policy p=none The email will go to the inbox / folder.

  2. Quarantine policy p=quarantine The email will go to a special 'quarantine' folders e.g. the junk or spam folder.

  3. Reject policy p=reject The email will bounce and will not end up in any inbox folder.

To verify your configuration, enter your domain name here.

If you don't want to process the DMARC reports yourself, consider using Postmark DMARC instead. They process the reports for you and send you a free weekly digest email.

Subscribe to our newsletter

The latest news, articles, and resources, sent to your inbox weekly.

More like this