AWS SES production access denied? What AWS actually wants

AWS rejects SES production access requests with 'for security purposes, we are unable to provide specific details.' Here is what that means, what the reviewer is really checking, the application wording that works, and what to do after a second denial.

You filled in the form, described your use case, and waited a day. Then this arrived:

Thank you for submitting your request to increase your sending limits. We are unable to grant your request at this time. For security purposes, we are unable to provide specific details.

That last sentence is why you are reading this. AWS will not tell you what went wrong, and the request form gives you no obvious second move. Thousands of people hit this every month, and most of them either give up on SES or start guessing.

This guide is the thing nobody wrote: what the denial actually means, what the reviewer is checking, how to write an application that passes, and what to do if you have already been denied once or twice.

What the denial actually means

The first thing to understand is that the message is a template. It is sent verbatim to everyone. It is not a description of your specific failure, and reading it closely for clues will not help you — there are none in there.

The second thing is that “for security purposes” does not mean AWS suspects you of anything. It means AWS will not publish its review criteria, because a published checklist is a checklist spammers would optimize against. The vagueness is deliberate and it is not personal.

What the denial does tell you is this: the reviewer could not satisfy themselves that you have a legitimate list and a working plan for bounces and complaints. That is the whole test. Almost every rejection comes down to an application that did not make those two things verifiable.

It helps to understand what AWS is protecting. SES sends from shared IP pools. Your sending reputation is partly Amazon’s sending reputation. A new account asking for production access is asking Amazon to lend you its standing with every mailbox provider on the internet, on the strength of a form. They are not being obstructive; they are being asked for something valuable.

The production access request form, field by field

The form is in the SES console under Account dashboard → Sending request. The CLI command is aws sesv2 put-account-details --production-access-enabled --mail-type TRANSACTIONAL|MARKETING --website-url ... --additional-contact-email-addresses .... Once submitted, you cannot edit the details until the review is complete.

Mail type

Choose Transactional or Marketing. Transactional means messages triggered by user action (password resets, receipts, notifications). Marketing means newsletters and campaigns. Choose the type that represents the majority of your volume. You can send both types from the same account, but declare what you actually send — AWS monitors complaint patterns after approval, and mismatch can trigger review.

Website URL

The domain or URL where recipients can learn about you. AWS checks this. A coming-soon page, a parked domain, or a 404 gets you denied. Use your actual product site, the page where users sign up, or your documentation if developer-facing. The URL does not have to be the exact domain you send from, but it should be obviously related.

Use case description

This is the make-or-break field. Most applicants write two sentences and get denied. The reviewer is trying to answer four questions:

  1. Where do your addresses come from? Not “users sign up” — say what form, what confirmation step, whether double opt-in, and whether you have purchased, rented, or imported third-party lists (the answer should be no).
  2. How do recipients stop receiving email? Every message has an unsubscribe link, processed automatically, takes effect immediately, and (if true) you support RFC 8058 one-click unsubscribe.
  3. How do you handle bounces and complaints? Not “we monitor bounces” — that is an intention. Say: “We have configured SES to send bounce and complaint notifications to SNS topics, subscribed an endpoint that writes to a suppression list, and every send checks the list.”
  4. Is your volume plausible? Include expected daily or monthly volume. Do not inflate to look established — implausible volume gets denied.

The application that passes describes a system you have already built, not a plan. See the templates below.

Additional contacts (optional)

Email addresses of other people who should be notified about account issues. Optional. Use real addresses or leave blank.

Preferred contact language

Choose English or Japanese.

Acknowledgement checkbox

Required. It states you will only send to people who requested your email and that you have bounce/complaint processes in place. Check it only if true — AWS will evaluate you against it later.

Two templates: transactional-only and transactional + marketing

These templates are for the use case description field. Replace everything in [brackets] with your actual system. Delete any sentence that is not true.

Template 1: Transactional email only

We send transactional email for [product name], a [one-sentence description]. Messages are password resets, login verification codes, order confirmations, and account notifications triggered by user actions. Recipients are registered users who provided an email address at signup and verified it by clicking a confirmation link.

All addresses are collected directly by us through our signup form at [example.com/signup]. We do not purchase, rent, scrape, or import addresses from third-party lists.

We have configured an SES configuration set with SNS event destinations for bounce and complaint notifications. These are delivered to a Lambda function that writes addresses to our suppression list in [DynamoDB / PostgreSQL / RDS]. Every send checks the suppression list before queuing. Hard bounces and complaints are suppressed automatically and permanently.

Transactional messages do not include an unsubscribe link because they are account-related notifications users cannot opt out of while maintaining an active account. Users can close their account at any time, which stops all email.

We expect approximately [N] emails per day, primarily password resets and [other transactional type]. Our sending domain [example.com] is verified with DKIM, and we publish a DMARC policy at _dmarc.example.com.

Template 2: Transactional + marketing email

We send both transactional and marketing email for [product name], a [one-sentence description]. Transactional messages are password resets, receipts, and account notifications triggered by user action. Marketing messages are a weekly newsletter and occasional product updates sent to users who explicitly opted in.

Transactional recipients are our registered users, who verify their email address by clicking a confirmation link. Marketing recipients opt in separately via a checkbox during signup or through a subscription form at [example.com/subscribe]. The checkbox is unticked by default. After opting in, recipients receive a confirmation email and are added to the list only after clicking the confirmation link. We do not purchase, rent, scrape, or import third-party addresses.

Every marketing message includes a visible unsubscribe link and a List-Unsubscribe header with RFC 8058 one-click unsubscribe support. Unsubscribes are processed programmatically and take effect immediately. Transactional messages are limited to user-triggered actions.

We have configured SES configuration sets for transactional and marketing sends separately. Both route to SNS topics that deliver bounce and complaint notifications to our application endpoint. The endpoint writes addresses to our suppression list in [DynamoDB / PostgreSQL / RDS], checked before every send. Hard bounces and complaints are suppressed permanently. We monitor bounce and complaint rates and treat sustained increases above 5% (bounces) or 0.1% (complaints) as incidents.

We expect approximately [N] emails per day at launch, split roughly [X]% transactional and [Y]% marketing. Our sending domain [example.com] is verified with DKIM, and we publish a DMARC policy. We separate transactional and marketing into different configuration sets to isolate reputations.

What AWS is actually checking

Four things, in roughly this order of weight.

1. Where your addresses come from, described concretely. “Users sign up on our website” is not an answer — it is a category. An answer is: “Addresses are collected through a signup form at example.com/subscribe. Every address receives a confirmation email and is only added to the sending list after the recipient clicks the confirmation link. We do not purchase, rent, scrape or import third-party lists.”

The word “confirmation” is doing real work in that sentence. Double opt-in is the single strongest signal you can give, because it is the one thing a spammer will not do.

2. How people stop receiving your email. The reviewer wants to know that unsubscribing is automatic and immediate, not a support ticket. Say that every message contains an unsubscribe link, that it is processed programmatically, that it takes effect immediately, and — if this is true — that you implement one-click unsubscribe per RFC 8058.

3. How you handle bounces and complaints. This is where most applications quietly fail. You need to describe a mechanism, not an intention. “We monitor bounces” is an intention. “Bounce and complaint notifications are delivered to SNS topics subscribed to our application endpoint, which adds the address to a suppression list; suppressed addresses are excluded from all future sends” is a mechanism.

Critically, you should have this already built when you apply. More on that below, because it is the highest-leverage thing in this guide.

4. Whether your described volume and your described business are consistent. If you are a two-person SaaS asking to send two million emails a month, explain why. If you are sending transactional email only, say so and give a realistic daily figure. Inflated numbers do not make you look established; they make the application look implausible, and implausible is the thing that gets denied.

Wire up SNS bounce and complaint handling before you apply

This is the step almost everyone skips, and it is the one that changes outcomes most.

The reason is simple: it converts every claim in your application from a promise into a description of something that already exists. The reviewer is trying to assess risk with very little information. An applicant who already has bounce plumbing in place is an applicant who has thought about the problem.

Practically, that means, before you submit:

  1. Create an SES configuration set and use it for your sends. This is what lets you route event notifications.
  2. Create SNS topics for bounces and complaints — separate topics make the handling code clearer, though one will do.
  3. Attach the topics to your configuration set as event destinations for the Bounce and Complaint event types. Add Delivery too if you want delivery confirmation in your logs.
  4. Subscribe an endpoint — an HTTPS endpoint, a Lambda, or SQS — that receives the notifications and writes the address to a suppression list.
  5. Actually suppress on send. A suppression list you never check is worse than none, because it gives you false confidence. Every send path must filter against it.
  6. Check the account-level suppression list in the SES console and enable both BOUNCE and COMPLAINT reasons if they are not already set. It is a setting, not a default you can rely on.
  7. Verify a domain with DKIM and publish the three CNAME records. Add a DMARC record while you are in the DNS console. None of this is strictly required for the application, but a domain with proper authentication reads as a real sender.

Then, in your application, describe what you built. You are no longer asking to be trusted; you are reporting a configuration.

A note on the account-level suppression list. This is a separate thing from the global suppression list AWS maintains across all of SES, and it is worth getting right before you apply. The account-level list is a setting: you enable it and choose which reasons it records, BOUNCE, COMPLAINT, or both. Newer accounts often have it switched on already, but do not assume — check it in the SES console under Suppression list, and enable both reasons if they are not set. It is still not a substitute for your own suppression list, because it does not know about the addresses that a specific client asked to be removed from a specific list.

Wording that works

Here is the shape of an application that passes. Every sentence in it must be true of your actual system — the point is not the phrasing, it is that the phrasing forces you to have built the thing. If a paragraph below is not true for you, the fix is to go and make it true, not to keep the sentence.

Use case. We send transactional email for [product], a [one-line description of what it does] used by approximately [N] customers. Messages are password resets, receipts, and account notifications triggered by a user action. We also send a weekly product newsletter to users who have explicitly opted in.

How we collect addresses. Transactional recipients are our own registered users, who provide an address at signup and confirm it by clicking a verification link before the account is activated. Newsletter recipients opt in separately, through a checkbox that is unticked by default, and receive a confirmation email; they are added to the list only after clicking the confirmation link. We do not purchase, rent, scrape, or import third-party lists, and we do not send to addresses we have not collected ourselves.

Unsubscribes. Every marketing message includes an unsubscribe link and a List-Unsubscribe header supporting one-click unsubscribe per RFC 8058. Unsubscribes are processed programmatically and take effect immediately; there is no manual step and no support ticket. Transactional messages are limited to messages the recipient’s own action triggered.

Bounces and complaints. We have configured an SES configuration set with SNS event destinations for bounce and complaint notifications. These are delivered to an endpoint that adds the address to our suppression list, which every send path is filtered against. Hard bounces and complaints are suppressed permanently and automatically. We monitor our bounce and complaint rates in the SES console and treat sustained increases as an incident.

Volume. We expect approximately [N] emails per day at launch, rising to roughly [N] within [timeframe]. Our sending domain [example.com] is verified with DKIM, and we publish a DMARC policy.

Some specific advice on tone. Write it as prose, in complete sentences. Be concrete about numbers, mechanisms and URLs. Do not pad it — a short application that answers all four questions beats a long one that circles them. And do not describe features you have not built, because if your bounce rate later suggests otherwise, that is a much worse conversation.

If you are running email infrastructure you deployed yourself, this is the point where the plumbing either exists or does not. Selva Mail wires up the SNS bounce and complaint topics, the suppression list and the RFC 8058 unsubscribe header as part of its deploy, which means the paragraphs above describe your setup on day one rather than a project you still have to do.

The region-retry strategy, honestly

You will find advice online telling you to request production access in a different AWS region if you are denied. This works often enough that it is worth understanding — and it is misunderstood often enough to be worth a warning.

Production access is granted per region. Reviews are handled by different queues, and there is a human element, so the same application can genuinely get different outcomes in us-east-1 and eu-west-1.

That said:

  • It is legitimate when your first application was fine and you got an inconsistent review. It is not a workaround for an application that did not answer the four questions.
  • Fix the application first. Retrying an unchanged application in a new region mostly buys you a second denial and a thinner-looking account history.
  • Choose the region you actually want. Sending from a region far from your users adds latency, and moving later means re-verifying identities and re-approving access. Pick on merit.
  • Do not fire off requests in six regions at once. It reads exactly like what it looks like.

After a second denial

A second denial means the application is not the problem you think it is. Change something real before applying again.

Re-read your application as a stranger. The most common failure is describing intentions in the passive voice — “bounces are monitored”, “users are able to unsubscribe”. Rewrite every such sentence to name the mechanism and the thing that runs it.

Check whether you actually have the plumbing. Send a test message to the SES mailbox simulator addresses (bounce@simulator.amazonses.com and complaint@simulator.amazonses.com) and confirm the address lands in your suppression list without you touching anything. If it does not, you have found the problem, and it is a good one to find — it would have hurt you in production anyway.

Reduce what you are asking for. A request for a modest daily volume from a plainly described business is easier to approve than a large one. You can request increases later, and an account with a clean sending history gets them easily.

Reply to the case rather than opening a new one. The support case from your denial can be reopened. Adding detail there — with specifics of what you have built since — gives the reviewer context that a fresh, identical-looking request does not.

Escalate through support if you have a plan. On a paid support plan you can ask for the case to be reviewed by someone who can discuss it. This is far more productive once you have made concrete changes, and not productive at all before then.

Consider whether the sending model is the real issue. Some use cases will not be approved, and no wording changes that: sending on behalf of addresses you did not collect, forwarding mail you received, mailing a list you acquired with a purchase, or any arrangement where the recipient never agreed to hear from you specifically. If that describes your case, the answer is not a better application — it is a different sending model.

What gets rejected: common reasons

AWS does not explain denials, but patterns emerge. These gaps consistently lead to rejection:

Vague use case with no mechanism. “We send emails to users” is a category. “We monitor bounces” is an intention. The fix: name the concrete system. “Bounce notifications are delivered via SNS to a Lambda that writes to a DynamoDB suppression table, checked before every send.” If you cannot write that sentence, build the system first.

No bounce or complaint handling. Applying without SNS bounce and complaint topics configured is the most common failure. Build the suppression system, then describe it. If you describe a system you have not built and get approved, your bounce rate will climb and AWS will place your account under review within days.

Purchased, rented, or scraped lists. AWS does not approve production access for third-party lists. If addresses came from a list broker, data provider, or scrape, the application is denied. Addresses migrated from your previous platform (Mailchimp, etc.) are fine — describe the original collection and migration date.

Coming-soon or incomplete website. Placeholder pages, domain-for-sale pages, or “launching soon” with no content gets denied. Launch a minimal public site first — a landing page explaining the product is enough.

MailType mismatch. If you select “Transactional” but describe newsletters, that is inconsistent. Newsletters are marketing. Select the type that matches what you actually send.

Unrealistic volume with no explanation. Requesting 100,000 emails per day for a week-old site with 50 signups is implausible. Explain high volume if legitimate, or request modest limits and increase after launch.

What happens after you submit

Once submitted, you cannot edit until review completes. AWS provides an initial response within 24 hours. You receive an email with approval or denial.

If approved

Your account moves to production immediately. Sandbox restrictions lift: you can send to any recipient address (verified identities still required for From/Source), the 200-message-per-24-hours and 1-message-per-second limits are removed. Daily send quota appears in the SES console under Account dashboard → Sending limits.

Approval is not the finish line. AWS monitors accounts continuously. If bounce rate exceeds 5% or complaint rate exceeds 0.1%, AWS can place your account under review or probation. Enable CloudWatch alarms at 4% (bounces) and 0.08% (complaints) for early warning.

If denied

The email says “we are unable to grant your request” and “for security purposes, we cannot provide specific details.” This is a template sent to everyone, not a description of your specific failure.

Fix the application first before reapplying. Most denials are for vague use cases or missing bounce handling. Reply to the support case if you built the suppression system after the initial denial — AWS can reopen and re-review. Do not assume the denial means your use case is not allowed; legitimate senders get denied for vague applications.

Once you are approved

Production access is the beginning, not the finish line. AWS can and does put accounts back under review.

Watch the two numbers in the SES console that matter: bounce rate and complaint rate. AWS starts paying attention around 5% bounces and 0.1% complaints. Both are lagging indicators of list quality, so react to a trend rather than waiting for a threshold.

Beyond that, the habits that keep a sending domain healthy are the ordinary ones: never send to an address that hard-bounced, honor unsubscribes instantly, keep transactional and marketing traffic separated so a campaign cannot damage delivery of password resets, and re-engage or drop addresses that have not opened anything in months. Grading contacts on engagement and simply not mailing the dead ones is the cheapest deliverability work available.

Separating transactional and marketing sends onto different domains (or subdomains) protects your password resets and receipts from campaign mistakes. Split your sending domains before you need to covers how to set up the split, why a subdomain does not inherit the root’s reputation, and what AWS recommends for custom MAIL FROM configuration.

None of that is exotic. It is just the part that has to be true before the application is worth writing.

Stop paying for the same contacts
every month.

$497 once. Runs on your infrastructure, sends through your own AWS SES account. Launch buyers get agency rights permanently — unlimited client workspaces. First 100 licenses.

or email us directly — hi@selva.run