Wraps Logo
DocsHome
Guide

Domain Verification

Set up DKIM, SPF, and DMARC for your domain to improve deliverability and protect your sender reputation.

6 min read

Why Verify Your Domain?

Email authentication proves to receiving servers that your emails are legitimate and haven't been tampered with. If you're new to email infrastructure, learn how email actually works first. Without authentication:

  • Emails are more likely to land in spam folders
  • Spammers can spoof your domain to send phishing emails
  • Your sender reputation can be damaged by abuse

The Three Pillars of Email Auth

  • DKIM — Signs emails cryptographically to prove they weren't modified
  • SPF — Declares which servers can send email for your domain
  • DMARC — Tells receivers what to do with emails that fail DKIM/SPF checks

Automatic DNS Management

The Wraps CLI can automatically create all required DNS records during wraps email init if you have the appropriate environment variables set for your DNS provider.

DNS ProviderRequired Environment VariableOptional
AWS Route53(uses AWS credentials)AWS_PROFILE
Vercel DNSVERCEL_TOKENVERCEL_TEAM_ID
CloudflareCLOUDFLARE_API_TOKENCLOUDFLARE_ZONE_ID

Setup Instructions

Vercel DNS

Create an API token at vercel.com/account/tokens

GNU Bashterminal.sh
export VERCEL_TOKEN=your_token_here# Optional: for team accountsexport VERCEL_TEAM_ID=team_xxxxx

Cloudflare

Create an API token at dash.cloudflare.com/profile/api-tokens. The token needs Zone.DNS (Edit) permission.

GNU Bashterminal.sh
export CLOUDFLARE_API_TOKEN=your_token_here# Optional: auto-detected if not setexport CLOUDFLARE_ZONE_ID=your_zone_id

AWS Route53

No additional setup required if you have a hosted zone for your domain. The CLI uses your existing AWS credentials.

Skip manual DNS setup

With automatic DNS management, you can skip Steps 2-4 below. The CLI will create DKIM, SPF, DMARC, and MX records for you during wraps email init.

Manual DNS Setup

If you prefer to add DNS records manually, or your DNS provider isn't supported, follow the steps below.

1
Add Your Domain to SES

Using Wraps CLI

GNU Bashterminal.sh
npx @wraps.dev/cli email domains add -d yourdomain.com

Using AWS Console

  1. Open the Amazon SES console
  2. Go to Identities Create identity
  3. Select Domain as the identity type
  4. Enter your domain name and click Create

2
Set Up DKIM

After adding your domain, SES generates 3 DKIM tokens. You need to add these as CNAME records in your DNS.

Get Your DKIM Records

GNU Bashterminal.sh
npx @wraps.dev/cli email domains get-dkim -d yourdomain.com

SES will display 3 CNAME records that you need to add to your DNS:

DKIM records displayed in SES console

Add Records to Your DNS

Copy all 3 CNAME records and add them in your DNS provider (Route 53, Cloudflare, Namecheap, etc.). The format looks like:

DKIM Records
# You'll get 3 CNAME records like this:abc123._domainkey.yourdomain.com → abc123.dkim.amazonses.comdef456._domainkey.yourdomain.com → def456.dkim.amazonses.comghi789._domainkey.yourdomain.com → ghi789.dkim.amazonses.com
Adding CNAME records in DNS provider

Important: Record Name Format

Copy the exact record names from SES. Don't add extra underscores or modify them. Some DNS providers automatically append your domain, so you may only need to enter the part before your domain name.

3
SPF (Automatic)

Good news: SPF is automatic!

When you send through Amazon SES, the MAIL FROM domain is a subdomain of amazonses.com, which already has SPF configured. No additional setup required.

If you want to use a custom MAIL FROM domain (advanced), see the AWS documentation.

4
Set Up DMARC

DMARC tells receiving mail servers what to do when emails fail authentication checks. SES will prompt you to set up DMARC:

DMARC setup instructions in SES console

Add this TXT record to your DNS:

DMARC Record
# Add this TXT record to your DNS:Name:  _dmarc.yourdomain.comType:  TXTValue: v=DMARC1; p=quarantine; sp=quarantine; np=reject; rua=mailto:dmarc@yourdomain.com

DMARC Policy Options

PolicyValueAction
Monitorp=noneNo enforcement, just collect reports
Quarantinep=quarantineSend failing emails to spam
Rejectp=rejectReject failing emails entirely

Recommended: Start with quarantine

Use p=quarantine to start. Once you've confirmed all legitimate emails pass, you can upgrade to p=reject.

5
Verify Your Setup

After adding DNS records, verify everything is configured correctly:

GNU Bashterminal.sh
npx @wraps.dev/cli email domains verify -d yourdomain.com

DNS propagation takes up to 72 hours

DKIM verification typically completes within a few hours, but can take up to 72 hours for DNS to propagate worldwide.

Custom Tracking Domains

SES rewrites every tracked link to r.us-east-1.awstrack.me before it reaches the inbox. That host is shared by every SES customer, and it is what your recipients see when they hover a link. A custom tracking domain replaces it with a hostname under your own domain, such as track.mail.yourdomain.com.

This only matters when open or click tracking is on. With both off, SES leaves your links alone and there is nothing to rewrite.

One tracking domain per domain you add

The redirect domain is a property of the SES configuration set, not of the domain identity. Wraps creates one configuration set per domain you add, so every added domain carries its own tracking domain. SES also requires the redirect domain to sit under the sending domain, and the CLI enforces that: track.mail.yourdomain.com is valid for mail.yourdomain.com, while track.yourdomain.com is not. The default suggestion is always track.<domain>.

That rule decides what happens with subdomains. If you added mail.yourdomain.com with wraps email domains add, it has its own configuration set and needs its own tracking domain. If you only added yourdomain.com and send as a subdomain of it, the send falls back to your primary domain's configuration set and those links use the primary's tracking domain. Several sending domains cannot share one tracking host.

Set one on a domain you already added

Run it as two commands. The HTTPS step refuses to start until a tracking domain exists.

GNU Bashterminal.sh
# 1. Set the tracking domainnpx @wraps.dev/cli email domains config -d mail.yourdomain.com \  --tracking-domain track.mail.yourdomain.com# 2. Then turn on HTTPS for itnpx @wraps.dev/cli email domains config -d mail.yourdomain.com --tracking-https

Your primary domain is the exception. Its tracking domain belongs to the Pulumi stack, so domains config rejects it. Use wraps email upgrade and choose "Add/change custom tracking domain" instead. To go back to the shared SES host, pass --tracking-domain none.

The DNS record

A tracking domain needs one CNAME. Wraps creates it for you on Route 53, Vercel, and Cloudflare. On every other provider the CLI prints the record and you add it by hand.

dns-record.txt
# CNAME for the tracking domain (plain HTTP tracking):Name:  track.mail.yourdomain.comType:  CNAMEValue: r.us-east-1.awstrack.me

The value is r.<region>.awstrack.me for plain HTTP tracking. With HTTPS enabled it becomes your CloudFront distribution domain instead, and the CLI swaps the record for you.

HTTPS tracking links

--tracking-https requests an ACM certificate and puts a CloudFront distribution in front of the tracking domain, both in your own AWS account. Certificate validation takes 5 to 30 minutes. The distribution is created only once the certificate reaches ISSUED, so run the same command again after that to finish the switch.

HTTPS costs one CloudFront distribution

Fractions of a cent per 10,000 tracking requests, and the certificate is free. It is still one more piece of infrastructure in your account to keep track of. Plain HTTP tracking works without it, and the links say http:// when recipients hover them.

Every domain at once

There is no flag that covers all your domains, because each one needs its own hostname. wraps email domains list --json reports every managed domain and its current tracking domain, so a loop covers the rest.

GNU Bashterminal.sh
npx @wraps.dev/cli email domains list --json \  | jq -r '.data.domains[]      | select(.managed and (.isPrimary | not) and (.trackingDomain == null))      | .domain' \  | while read -r d; do      npx @wraps.dev/cli email domains config -d "$d" --tracking-domain "track.$d"    done

The --domain flag is required in JSON mode, which is why this loops rather than running one command. Add a second pass with --tracking-https once the CNAMEs resolve. Full flag details live in the email CLI reference.

Troubleshooting

Domain still shows "Pending" after 72 hours
  • Double-check CNAME record names match exactly (no extra underscores)
  • Some DNS providers auto-append your domain — you may need to remove it from the record name
  • Try adding a trailing period (.) to the CNAME value for fully qualified domain names
  • Ensure the underscore (_) is present in record names
DMARC reports show failures
  • Ensure DKIM records are correctly published
  • Check that you're sending from a verified identity
  • If using a custom MAIL FROM domain, verify SPF is configured
Links still point at awstrack.me
  • Check the tracking CNAME exists and resolves. Until it does, SES keeps using the shared host
  • SES only accepts a redirect domain once its sending domain is verified. If you set one on an unverified domain, re-run wraps email domains verify after verification to apply it
  • Confirm you are sending from the domain you configured. A subdomain that was never added uses your primary domain's tracking domain
  • Open and click tracking must be enabled, otherwise SES never rewrites the link
HTTPS tracking stays pending
  • ACM validation takes 5 to 30 minutes. Re-run --tracking-https once the certificate is ISSUED to create the distribution
  • A CAA record on your domain that omits amazon.com blocks ACM from issuing the certificate
  • The validation CNAME that ACM asks for has to be published like any other record

Verification Checklist

  • Domain added to SES
  • 3 DKIM CNAME records added to DNS
  • Domain status shows "Verified" in SES
  • DMARC TXT record added to DNS

Next Steps

Request Production Access

Now that your domain is verified, request production access for faster approval.

Production Access
Send Your First Email

Start sending authenticated emails with the Wraps SDK.

Email Quickstart