Details below are from the Amazon Cognito, Amazon SES and AWS Amplify documentation on 29 October 2026. Check them for current details.
What Cognito sends
| Sent when | Holds | Valid for | |
|---|---|---|---|
| Sign-up confirmation | Someone signs up, or asks for the code again | A code, or a link if you choose links | 24 hours |
| Forgotten password | Someone asks to reset their password, or an admin resets it | A code | 1 hour |
| Invitation | You create the user yourself | The username and a temporary password | 7 days by default |
| Attribute verification | Someone changes their email address | A code | 24 hours |
| Sign-in code | Email MFA, or passwordless sign-in with a one-time code | A code | Minutes: an MFA code lasts 3 by default, up to 15 |
The invitation comes from AdminCreateUser, and an admin reset (AdminResetUserPassword) sends the same email as ForgotPassword. Sign-in codes by email need the Essentials or Plus feature plan and your user pool sending with your own Amazon SES. The forgotten-password and email-change emails use the same template as the sign-up code, so they look alike.
First: the default sender sends 50 emails a day
A new user pool sends from no-reply@verificationemail.com, Cognito’s own sender. It sends to any address, so a test inbox gets the mail, but only 50 emails a day per AWS account, and the count resets at 09:00 UTC. A test suite that signs up a few dozen accounts uses that up, and the emails stop until the next reset.
For anything more than trying it out, send with Amazon SES: in the user pool, open Authentication methods → Email configuration, choose Edit, and pick a From address you’ve verified in SES.
Then: take your own SES out of the sandbox
A new Amazon SES account starts in the sandbox, which only delivers to verified addresses and domains, in each Region separately. Cognito hands the email to SES, and SES won’t send it to a test inbox. Request production access in the SES console for the Region your user pool sends from. Test email not arriving? covers SES and the other providers.
Amplify Gen 2
defineAuth sets the same things in code. verificationEmailStyle picks a code ('CODE') or a link ('LINK') for sign-up, and senders.email sends from your own SES address instead of the default sender:
import { defineAuth } from '@aws-amplify/backend';
export const auth = defineAuth({
loginWith: {
email: {
verificationEmailStyle: 'CODE',
verificationEmailSubject: 'Your Acme verification code',
verificationEmailBody: (createCode) => `Your Acme verification code is ${createCode()}.`,
},
},
senders: {
email: {
fromEmail: 'no-reply@acme.example',
fromName: 'Acme',
},
},
});
The From address has to be verified in Amazon SES, and Amplify’s docs say to request production access first.
Test it by hand
- Create an address in Proxy Mail QA.
- Sign up in your app with it.
- The code or link appears on the address’s row within seconds. From the default sender, the row names the service as Amazon Cognito.
Then try a forgotten password and an email change. An invitation holds a temporary password rather than a code, so open it in the address’s inbox to read it.
Automate it
import { test, expect } from 'proxymail-qa/playwright';
test('Cognito sign-up sends a working code', async ({ page, qa }) => {
const { address, password } = await qa.createAddress({ password: true });
const submitted = new Date();
await page.goto('/signup');
await page.getByLabel('Email').fill(address);
await page.getByLabel('Password').fill(password);
await page.getByRole('button', { name: 'Create account' }).click();
const { value: code } = await qa.waitForCode(address, { since: submitted });
await page.getByLabel('Confirmation code').fill(code);
await page.getByRole('button', { name: 'Confirm' }).click();
await expect(page.getByText('Welcome')).toBeVisible();
});
Match the labels to your sign-up page. The generated password is 16 characters with every kind a Cognito password policy can require: upper and lower case letters, a number and a symbol. In a reset test, pass since the moment you asked for the reset: the reset email looks like the sign-up one, and since makes sure the wait returns the new code. More in Test sign-up emails in Playwright.