Limits below are from Supabase’s documentation on 17 October 2026. Check it for current details.
What Supabase sends
Each has its own template in the dashboard: Confirm signup, Invite user, Magic Link, Change Email Address, Reset Password and Reauthentication. By default they hold a link; add {{ .Token }} to a template to send a 6-digit code instead.
First: the default sender won’t email test addresses
Supabase’s built-in email service is meant for trying things out. Its documentation says it:
- only delivers to addresses on your project’s team, refusing others with “Email address not authorized”;
- sends at most 2 messages an hour;
- isn’t meant for production.
So sign-up tests fail before they start. Set up custom SMTP under Authentication → Emails (any provider: Resend, Amazon SES, Postmark, Mailgun and others), and make sure that provider isn’t in its own sandbox mode. Test email not arriving? covers each one.
Then: fix links to localhost
The Site URL defaults to http://localhost:3000, so confirmation and magic links from your deployed app can send people to localhost. Set it to your app’s URL and add every environment to Redirect URLs. More in why emails link to localhost.
Test it by hand
- Create an address in Proxy Mail QA, with a persona and password if your form asks.
- Sign up in your app with it.
- The confirmation link or code appears on the address’s row within seconds. Open or copy it, and check where it lands.
Then do the same for a magic link, a password reset and an invite. Each email stays in the address’s inbox, so anyone on the project can check it later.
Automate it
import { test, expect } from 'proxymail-qa/playwright';
test('Supabase sign-up confirms the email', async ({ page, qa }) => {
const { address, password } = await qa.createAddress({ persona: true, 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: 'Sign up' }).click();
const { value: link } = await qa.waitForLink(address, { type: 'verify', since: submitted });
await page.goto(link);
await expect(page).toHaveURL(/staging\.example\.com/);
});
checkEmail(address, { expectHost: 'staging.example.com' }) also fails the test if the link ends up anywhere else. More in Test sign-up emails in Playwright. Built with Lovable, Bolt or v0? Their guides cover the Supabase settings each one sets up: Lovable, Bolt, v0.