Why Are My Amazon SES Emails Going to Spam?
Amazon SES is a good sending service that will happily deliver a badly configured message to the spam folder at enormous scale. It is deliberately unopinionated: you hand it a message, it hands the message to the receiver, and it takes no position on whether your domain deserves the inbox.
That design is why SES mail ends up in spam for reasons that have nothing to do with SES. Three causes cover almost all of it, and they are worth checking in order, because the first one is both the most common and the least obvious.
Cause one: the default MAIL FROM breaks DMARC alignment
This is the SES-specific failure, and it catches setups that look perfect everywhere else.
Every message has two From addresses. The one your reader sees, in the From: header, and the invisible envelope sender in MAIL FROM, which is where bounces go. SPF is checked against the envelope sender, not the visible one.
By default, SES sets the envelope sender to a subdomain of amazonses.com. Your recipient sees this in the headers:
Return-Path: <0100018f2c@eu-west-1.amazonses.com>
From: hello@example.com
Authentication-Results: mx.google.com;
spf=pass (google.com: domain of 0100018f2c@eu-west-1.amazonses.com
designates 54.240.8.1 as permitted sender)
dkim=pass header.i=@example.com
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=example.com
Read the spf=pass line carefully. SPF passed, for amazonses.com. That domain has nothing to do with example.com, so for DMARC purposes SPF is not aligned and contributes nothing. In that header DMARC still passes, but only because DKIM is doing all the work on its own.
Which is fine, right up until a message gets forwarded, a security gateway rewrites something, or DKIM fails for any other reason. At that point you have no second leg to stand on and the message fails DMARC outright.
The fix is a custom MAIL FROM domain: a subdomain such as mail.example.com that you configure on the SES identity and back with the MX and SPF records SES gives you. After that, SPF passes for your own subdomain, which aligns with your From domain, and both legs hold.
Do this: paste the raw headers of an SES message into the free email header analyzer and look at which domain the spf=pass line names. If it says amazonses.com, configure a custom MAIL FROM today.
Cause two: shared IP reputation you do not control
Unless you have paid for a dedicated IP, your SES mail goes out on a shared pool. Your domain reputation is yours. The IP reputation is shared with whoever else is sending from that address today.
This produces a specific and confusing symptom: your domain is clean everywhere, every record passes, and mail still lands in spam at one provider and not another. That pattern points at the IP, not at you.
It is worth being clear about what you can do here, because the honest answer is “not much directly”. You cannot clean an IP you share. What you can do is make sure the problem is actually the IP before you go looking for it in your own setup, and make sure your domain-level signals are strong enough to carry the message despite a mediocre IP.
Checking that split is quick. A free blocklist check on your domain queries the domain and your mail server IPs separately against the major lists, so a listing on one and not the other tells you which problem you have.
The instinct at this point is often to buy a dedicated IP. Below roughly 100,000 messages a month, that usually makes things worse rather than better: a dedicated IP has no reputation until you build one, and it decays during any quiet period. The shared pool is the better default for most senders, precisely because it is always warm.
Do this: run the blocklist check and note whether the listing, if any, is on the domain or on the mail server IP. Only the first one is yours to fix.
Cause three: the list, and the two numbers AWS watches
SES publishes a reputation dashboard in the console with two numbers that matter: bounce rate and complaint rate. AWS asks bulk senders to keep bounce rate under 5 percent and complaint rate under 0.1 percent.
Those are the thresholds at which AWS starts paying attention to your account. Mailbox providers start paying attention considerably earlier. A 3 percent bounce rate will not get your SES account reviewed, and it will absolutely affect where Gmail puts your mail.
Both numbers are downstream of one thing: who is on your list and how they got there. A purchased list, an old export, or a signup form with no confirmation step will produce bounces and complaints no amount of DNS configuration can offset.
Do this: open the SES account dashboard, write down today’s bounce and complaint rates, and remove every hard bounce from your list before the next send.
Verifying the fix
After changing MAIL FROM or DKIM, wait for the DNS TTL to expire, then send yourself a message and read the headers again. The spf=pass line should now name your own subdomain, and dmarc=pass should be supported by both SPF and DKIM rather than DKIM alone.
The free email health check reads your published SPF, DKIM, DMARC and MTA-STS records back out of DNS alongside your blocklist status, which is the fastest way to confirm the records you configured in the SES console actually made it into your zone.
That answers for one domain, at the moment you ask it. Which is the real gap.
SES configuration is not a thing that stays fixed. A custom MAIL FROM depends on an MX record that a DNS migration can quietly drop. DKIM depends on three CNAMEs that a well-meaning cleanup can remove. Shared-pool IP reputation changes because of somebody else’s send, on a day you were not looking. Nothing in SES will tell you: the API call still returns a message ID, the send still succeeds, and the mail quietly starts landing in spam.
Closing that gap is what LitInboxes does. Each monitored domain is re-checked every 6 hours across DNS records, 8 high-signal blocklists on every plan and 24 on Pro, DMARC aggregate reports and Google Postmaster reputation, with a dated history so you can see exactly when something changed and an alert on the change rather than on a schedule. Email alerts are on every plan; Slack, Discord and webhook alerts are on Pro. There is a live demo if you want to see the view first.
If SES turns out not to be the problem, the full spam diagnostic walks the other causes in order of likelihood.
The checklist
- Read the headers of a real SES message and check which domain
spf=passnames. - If it names
amazonses.com, configure a custom MAIL FROM subdomain and publish the MX and SPF records SES gives you. - Confirm Easy DKIM is verified and all three CNAMEs resolve.
- Publish a DMARC record at
p=nonewith aruaaddress and start reading the reports. - Check the domain and the sending IPs against blocklists separately.
- Write down today’s bounce and complaint rates from the SES dashboard.
- Remove every hard bounce and every address with no engagement in months.
- Re-read the headers after the TTL expires and confirm SPF now aligns.
How to stop Amazon SES email from landing in spam
- Set a custom MAIL FROM domainIn the SES console, open your verified domain identity and configure a custom MAIL FROM subdomain such as mail.example.com. Publish the MX and SPF records SES gives you. Without this, SPF passes for amazonses.com and fails DMARC alignment.
- Confirm Easy DKIM is enabled and verifiedPublish the three CNAME records SES provides and wait for the identity to show as verified. DKIM signed with your own domain is what keeps DMARC passing when a message is forwarded.
- Publish a DMARC record and read the reportsStart at p=none with a rua address so you can see which sources pass alignment. Without reports you are guessing about which of your senders is failing.
- Check the SES reputation dashboardOpen Account dashboard in the SES console. AWS asks bulk senders to keep bounce rate under 5 percent and complaint rate under 0.1 percent. Above those, placement degrades before AWS takes any action.
- Check your domain and sending IPs against blocklistsOn the shared SES pool your IP reputation is partly out of your hands. Confirm whether the listing is on your domain, which is yours to fix, or on the IP, which is not.
- Clean the list before the next sendRemove hard bounces immediately and drop addresses that have not engaged in months. Bounce and complaint rates are the two numbers AWS actually acts on.
Frequently asked questions
Does Amazon SES have a bad sending reputation?
No. SES is used by very large legitimate senders. What it does not do is protect you from your own configuration or list quality, and on the shared IP pool your neighbours affect your IP reputation without affecting your domain reputation.
Why does my SES email fail DMARC when SPF passes?
Because by default SES uses amazonses.com as the MAIL FROM domain. SPF passes for that domain, not for yours, so it does not align with your From address. Configuring a custom MAIL FROM subdomain fixes it.
Do I need a dedicated IP on SES?
Usually not. Below roughly 100,000 messages a month a dedicated IP is a liability, because you have to keep it warm and a quiet period damages it. The shared pool is the better default for most senders.
What bounce and complaint rates does AWS expect?
AWS asks bulk senders to keep bounce rate under 5 percent and complaint rate under 0.1 percent. Sustained rates above those put the account under review, and placement usually degrades well before that point.