Connect AWS
Connect an AWS account to Stamp0 with a CloudFormation Quick Create link, verify it with the RoleArn output, and get your SES account out of the sandbox.
A connection is one AWS account and region (or one Cloudflare account: see Connect Cloudflare). It belongs to your organization, and any number of projects can send through it. Stamp0 never stores AWS keys: it assumes a role in your account, with an external ID only your connection knows, each time it calls SES or S3.
1. Create the stack with Quick Create
In the dashboard (Settings › AWS connection, or the onboarding after sign-up), pick the SES region you want to send from. Stamp0 creates the connection and shows a CloudFormation Quick Create link with every parameter filled in.
Connections are managed by organization owners and admins in the dashboard only. A connection decides where every project of the organization stores and sends mail, so API keys (which belong to one project), OAuth clients such as MCP and the CLI can read a connection's status but cannot create, verify, re-point or delete it, and never see its external ID or ingest token.
Open the link while signed in to the AWS account you want to connect. Review the parameters, tick I acknowledge that AWS CloudFormation might create IAM resources with custom names, and choose Create stack. The stack is named stamp0-con-… and usually finishes in one to two minutes.
| Parameter | Default | What it does |
|---|---|---|
ConnectionId, ExternalId, IngestSecret | Filled in | Tie the stack to your connection. The ingest token travels in the link's fragment, so it never reaches AWS's servers, and CloudFormation hides it (NoEcho) |
EnableRoute53Dns | false | Lets Stamp0 publish DKIM, DMARC and MAIL FROM records in Route 53 |
EnableInbound, InboundRecipients | false, empty | Receive mail for the domains or addresses you list. See receiving |
ExistingReceiptRuleSetName, ExistingReceiptRuleAfter | Empty | Add the Stamp0 rule to the rule set you already use |
RetentionDays | 90 | How long bodies, attachments and inbound mail stay in the bucket |
2. Verify with the RoleArn output
When the stack reaches CREATE_COMPLETE, open its Outputs tab and copy RoleArn (arn:aws:iam::<account>:role/Stamp0Access-con_…). Paste it into the dashboard and choose Verify connection. Instead of the ARN you can enter your 12-digit AWS account ID, and the stack name if you renamed the stack. Verification runs in the background: the connection is verifying, then connected, or error with a last_error such as access_denied (the external ID or account does not match), configuration_set_missing or role_arn_mismatch. Once connected, Stamp0 re-checks the account every six hours, so sandbox status and quota stay current.
What the stack creates
The stack runs no code: no Lambda functions and no servers, so there is nothing for you to patch.
| Resource | Purpose |
|---|---|
IAM role Stamp0Access-<connection> | Trusts only Stamp0's platform role, and only with your connection's external ID |
SES configuration set stamp0-<connection> | Routes delivery, bounce, complaint, open and click events to EventBridge |
| EventBridge connection, API destination and rules | Push those events (and new inbound mail) to https://api.stamp0.com/ingest, with 24 hours of retries and a dead-letter queue |
S3 bucket stamp0-<id> | Email bodies, attachments and raw inbound mail. Encrypted, private, TLS only, expiring after RetentionDays. Kept when you delete the stack |
| SES receipt rule (optional) | Stores mail for exactly the recipients you list, in the bucket |
The stack costs about $0.40 a month (the Secrets Manager secret behind the EventBridge connection) plus S3 storage. Sending is billed by AWS at SES prices.
What the role may do
- Identities: create SES identities only with the tag
stamp0:connection=<your connection>, and send from, change or delete only identities that carry that tag. It cannot tag an identity you created yourself, so your other SES identities stay out of reach. If SES already has an identity for a domain you add, Stamp0 reports a conflict and never takes it over. - Sending: only through this connection's configuration sets.
- Account: read account details and quotas, and manage the account-level suppression list, in this region.
- Storage: read and write its own bucket.
- Route 53 (only with
EnableRoute53Dns=true): create or updateCNAME,MXandTXTrecords named<token>._domainkey.*,_dmarc.*,send.*orbounce.*. No deletes and no other names.
It has no IAM, EventBridge or KMS permissions, cannot change receipt rules or switch the active rule set, and cannot read other buckets. Delete the stack to revoke access at once.
Receiving mail
Receiving is off by default. Set EnableInbound=true and list domains (acme.co) or addresses (support@acme.co) in InboundRecipients; mail for anything else in your account is never stored or forwarded. To receive a new domain later, update the stack with the longer list. A domain with receiving enabled shows the exact update it still needs under receiving.setup.
SES allows one active receipt rule set per region. If you already have one, name it in ExistingReceiptRuleSetName and the Stamp0 rule is added to it; it only stores a copy, so your later rules still run. Otherwise the stack creates the set stamp0-<connection> and you activate it once, in the SES console or with aws ses set-active-receipt-rule-set --rule-set-name stamp0-con_…. Stamp0 never switches rule sets for you.
SES receives mail only in the regions where AWS offers email receiving, which include us-east-1, us-east-2, us-west-2, eu-west-1, eu-central-1 and ap-southeast-2. Elsewhere the stack ignores EnableInbound: sending works and receiving stays off. Add a second connection in a receiving region if you need both.
Leave the SES sandbox
A new SES account starts in the sandbox of each region: it sends only to verified addresses, at most 200 messages a day and one a second. After verification, the connection shows its sandbox_status (sandbox or production) and its sending_quota.
To send to anyone, request production access from the same account and region:
-
Verify a domain in Stamp0 first, so the request names a domain with DKIM, MAIL FROM and DMARC in place.
-
In the SES console, open Account dashboard → Request production access, choose Transactional, and describe what you send, to whom, how recipients opt in, and how you handle bounces and complaints (Stamp0 records them and keeps the suppression list). Or submit it with the AWS CLI:
aws sesv2 put-account-details --region us-east-1 \ --production-access-enabled --mail-type TRANSACTIONAL \ --website-url https://acme.co --contact-language EN \ --use-case-description "Receipts and password resets for acme.co customers…" -
AWS usually answers within a day. The next re-check (or Verify connection) shows
productionand the new quota.
The MCP tool stamp0.sandbox.prepare drafts the use case text and the CLI command from your account data; you review and submit it yourself. How to get out of the SES sandbox covers what reviewers look for.
Stack updates
The template is versioned: the stack's StackVersion output, shown as the connection's stack_version under Settings → Connection. Older stacks keep working when a new version ships; a feature that needs the newer template says so. For example, per-domain tracking and TLS need v1.4.0, and on an older stack a domain reports tracking_status: stack_update_required. To update, choose Update on the stack in CloudFormation, Replace existing template with the current template URL, and keep your parameters. Nothing changes in your account until you approve the change set.
Migrate from Resend
Move from Resend to Amazon SES in your own AWS account without changing code. Keep the Resend SDK, set the base URL to https://api.stamp0.com and verify your domain.
Connect Cloudflare
Send transactional email through Cloudflare Email Service and receive it with Email Routing, in your own Cloudflare account. Two API tokens, what Stamp0 deploys, limits, costs and the transactional-only rule.