PigeonAtlas
← Deliverability notes

September 22, 2026 · 9 min read

"Email address is not verified" in Amazon SES: the five causes, in order

SES refuses the send and names an identity. Which identity it names tells you which of five things is wrong — the sandbox, the region, the address you verified, a verification that lapsed, or an IAM policy. One command tells you which.

The error names an identity, and that name is the answer:

Email address is not verified. The following identities failed the check
in region EU-CENTRAL-1: Acme <hello@mail.acme.com>

If the identity it names is your sender, the domain or address you send from is not verified in that region — or it was, and is not anymore. If it names your recipient, you are in the sandbox. Read which one it is before changing anything, because the five causes have five different fixes and four of them do nothing for the others.

Key takeaways

  • The error prints the identity and the region. Both are part of the diagnosis.
  • A named recipient means the sandbox: SES will only deliver to addresses you have verified until AWS grants production access.
  • Identities are per region. Verifying acme.com in us-east-1 does nothing for a send in eu-central-1.
  • Verifying a domain covers its subdomains and every address under it. Verifying a subdomain does not cover the parent.
  • A verification can lapse. SES keeps checking your DNS after the first success, warns you when the records go missing, and then revokes the setup — after which every send is refused, and re-verification has to be started from the beginning.
  • aws sesv2 get-email-identity answers all of this in one call.

Cause 1: you are in the sandbox, and the recipient is not verified

New SES accounts start in a sandbox where mail is delivered only to addresses and domains you have verified yourself. Send to anyone else and SES refuses the message and names the recipient in the error. This is by far the most common version of this error, and the one most likely to be misread: people see "email address is not verified", go and check their sending domain, find it verified, and get stuck.

Three ways out, depending on what you are doing:

  1. Verify the recipient too. Fine for testing with your own addresses.
  2. Use the mailbox simulator. Addresses such as success@simulator.amazonses.com and bounce@simulator.amazonses.com work in the sandbox without verification and let you exercise bounce and complaint handling properly.
  3. Request production access. It is a support case opened from the SES console, and the answer turns on whether you can describe where your recipients come from, what happens on bounces and complaints, and how people opt out.

Cause 2: the identity is verified in a different region

SES identities are regional. The docs put it plainly: to send from the same domain in more than one region, you have to create and verify a separate identity in each. A domain verified in us-east-1 is not verified in eu-central-1, and nothing in the console hints at the other region's state.

This is why the error prints the region in capitals. Compare it against the region your client is configured for:

aws sesv2 list-email-identities --region eu-central-1

If your identity is not in that list, it is somewhere else. Either verify it in the region you are sending from, or point the client at the region where it is already verified. Credentials work across regions; verification does not.

Cause 3: the From address is not covered by what you verified

Verification is inherited downward and never upward:

  • Verifying acme.com lets you send from hello@acme.com, user@mail.acme.com, user@a.b.acme.com — any address at any subdomain.
  • Verifying mail.acme.com lets you send from addresses at that subdomain and below. It does not let you send from hello@acme.com.

Two details in the same area catch people out:

Domain names are case-insensitive, email addresses are not. Verify acme.com and ACME.com works too. Verify sender@EXAMPLE.com and sender@example.com is still unverified.

The error prints the whole From header, display name and all — Acme <hello@mail.acme.com>. The identity being checked is the address inside the angle brackets. If that address is not what you expected, the bug is in whatever built the header, not in SES.

Cause 4: it was verified, and it stopped being verified

This is the one that costs a day, because nothing changed in your code and the console said "Verified" the last time anyone looked.

SES does not check your DNS once. It keeps checking. When the records go missing — a DNS migration, a provider that drops records it does not recognize, a zone rebuilt from a template — SES emails you to say it can no longer find them, gives you a deadline to republish, and then revokes the DKIM setup and stops signing. A domain that never finished verifying in the first place goes the same way: SES tells you to allow up to 72 hours for DNS to propagate, and an identity that is still not found at the end of that window ends up Failed rather than pending forever.

Either way, sending is refused with the error at the top of this post, from an identity the console has quietly moved to Failed.

Ask SES directly rather than trusting the console's summary:

aws sesv2 get-email-identity --email-identity mail.acme.com --region eu-central-1

The three fields that matter:

  • VerifiedForSendingStatusfalse means every send is refused, whatever else says.
  • DkimAttributes.StatusSUCCESS, PENDING or FAILED.
  • MailFromAttributes.MailFromDomainStatus — the same three values for your custom MAIL FROM subdomain.

There is no retry button, and no API call named "verify again". AWS's own instruction for a revoked setup is to start the procedure from the beginning. In practice that means republishing the records and then re-submitting the DKIM configuration, which resets the identity to Pending and starts the checks again:

# Easy DKIM: republish the three CNAMEs, then
aws sesv2 put-email-identity-dkim-attributes \
  --email-identity mail.acme.com --signing-enabled --region eu-central-1

# BYODKIM: re-submit the same selector and private key
aws sesv2 put-email-identity-dkim-signing-attributes \
  --email-identity mail.acme.com \
  --signing-attributes-origin EXTERNAL \
  --signing-attributes DomainSigningSelector=s1,DomainSigningPrivateKey=<base64 PKCS#8> \
  --region eu-central-1

We hit exactly this on our own house domain. It was registered with SES on 4 September, the DNS records went in later than that, SES had already stopped looking, and on 22 September a send was refused on a domain our own dashboard called verified. Re-submitting the key moved it to Pending, and it was SUCCESS within minutes — the records had been correct the whole time. Nothing was wrong except that nobody had asked SES what it thought.

If you build on SES, that is the lesson worth stealing: your own verification passing is not the same thing as SES's. Check VerifiedForSendingStatus on a schedule, or at least when a send is refused, and restart the check rather than recording a permanent failure.

Cause 5: an IAM policy that limits which identities you may use

A different error, often mistaken for this one:

AccessDeniedException: User 'arn:aws:iam::123456789012:user/app-ses' is not
authorized to perform 'ses:SendRawEmail' on resource
'arn:aws:ses:eu-central-1:123456789012:identity/hello@acme.com'

The identity is verified; the credentials are not allowed to send from it. This comes from a policy written narrowly during setup — a Resource listing specific identity ARNs, or a condition on ses:FromAddress — which then silently excludes every identity added afterwards. If a send starts failing on the day you add a domain, and the message says AccessDenied rather than MessageRejected, this is where to look.

The order to check, in one minute

  1. Read the identity in the error. Recipient → sandbox. Sender → keep going.
  2. Compare the region in the error with the region your client uses.
  3. Compare the address inside the angle brackets with what you actually verified — parent covers child, never the reverse.
  4. aws sesv2 get-email-identity and read VerifiedForSendingStatus. false with FAILED means the verification lapsed; republish and re-submit.
  5. If the error says AccessDenied instead, it is the IAM policy, not verification.

Or let something else hold this

None of the above is hard. It is just work that never ends: a key per domain, a MAIL FROM subdomain with its MX record, a verification that can lapse quietly, a region that has to match, an IAM policy that has to be kept current — before you get to bounces, complaints, suppression and a log of what you sent.

PigeonAtlas sits on SES and does that part. A domain gets its own 2048-bit DKIM key, the page shows every record with its own green tick, and the service now watches what SES itself says about the identity and restarts a lapsed verification on its own — a send that arrives during the gap waits and goes out, rather than failing. The API request shape is Resend's, so moving an existing integration is a base URL and a key.

The free plan is 1,000 emails a month from one verified domain, with no card. If you would rather keep running SES yourself, the checks above are the whole of it — and SPF, DKIM and DMARC, explained by what actually breaks covers the records themselves.

Frequently asked questions

Does verifying a domain mean I have to verify each address? No. A verified domain covers every address at it and at its subdomains. Verifying an individual address as well is only needed for advanced setups — assigning a configuration set to that address, authorizing another account to send as it, or overriding the domain's settings.

How long does verification take? Usually minutes once the records resolve. AWS asks you to allow up to 72 hours for DNS propagation, and an identity still unfound at the end of that window is marked Failed rather than left pending.

Why does SES say verified in the console but refuse my send? Check the region first — the console shows one region at a time, and it may not be the region your code sends from. If the region matches, read VerifiedForSendingStatus from get-email-identity: the console's badge can be stale in a way the API is not.

Can I send from an address at a domain I verified, without verifying the address? Yes, that is the point of a domain identity. The address just has to be at the verified domain or one of its subdomains, spelled exactly as it appears in the From header.

I use the mailbox simulator and still get this error. The simulator addresses bypass the recipient check, not the sender one. If the identity named in the error is your From address, the problem is on your side of the message and the simulator changes nothing.

PigeonAtlas does this part for you

We generate the DKIM key, show the exact records to publish, check them ourselves, and warn you when a domain ends up with two DMARC records.

Create an account