# Auth emails and templates

> How SupaHost sends Auth emails for your project, which of the five templates each action uses, the fields and placeholders you can edit, sending limits, and options when you need full control.

Source: https://supahost.app/docs/auth/email-templates · Updated 2026-11-11

Supabase Auth sends emails for sign-up confirmation, magic links, password resets, invites and email changes. On SupaHost these are sent for you: there's no SMTP server to set up, and you edit the wording of each email in the dashboard.

## How sending works

- Emails come from `noreply@supahost.app`. The sender name is your project's **App name** (or the project name if you haven't set one), so recipients see something like `Recipe Box <noreply@supahost.app>`.
- Custom SMTP isn't available on SupaHost. There's no setting for your own mail server or sender address.
- Auth sends at most 30 emails in its rate-limit window (`GOTRUE_RATE_LIMIT_EMAIL_SENT=30`). This is fixed. See [Rate limits](/docs/auth/rate-limits).

Set the App name in *Dashboard → your project → **Auth** tab → **Auth** card* (up to 60 characters) and click **Save Auth settings**. It also appears as the header at the top of every email.

## The five templates

| Template | Sent when | Typical code |
|---|---|---|
| Confirm sign-up | A user signs up with email and password, and "Skip email confirmation" is off | `signUp`, `resend({ type: 'signup' })` |
| Magic link | A user asks for a passwordless sign-in | `signInWithOtp` |
| Reset password | A user asks to reset their password | `resetPasswordForEmail` |
| Invite | You invite a user from your server | `auth.admin.inviteUserByEmail` |
| Change email | A user changes their email address | `updateUser({ email })` |

## Editing a template

Open *Dashboard → your project → **Auth** tab → **Auth emails***, pick the template, and edit its four fields:

| Field | Limit | Notes |
|---|---|---|
| Subject | 150 characters | The email's subject line |
| Heading | 150 characters | The large title inside the email |
| Message | 2000 characters | The paragraph under the heading |
| Button text | 40 characters | The label on the main button |

Click **Save email**. **Preview saved version** shows the email as it will be sent, and **Reset to default** goes back to SupaHost's wording. Only the instance owner can edit templates.

The fields are plain text. The layout, the button link, a fallback copy of the link and the one-time code are added automatically, so you can't break the link by editing the text.

### Placeholders

You can use these inside the fields:

| Placeholder | Value |
|---|---|
| `{{ .Email }}` | The recipient's address |
| `{{ .NewEmail }}` | The new address (Change email template) |
| `{{ .Token }}` | The one-time code (already shown in every email, but you can mention it in the text too) |
| `{{ .SiteURL }}` | Your project's Site URL |

For example, a friendlier Reset password message for an invoicing app:

```
Subject:  Reset your Ledgerly password
Heading:  Let's get you back in
Message:  Someone (hopefully you) asked to reset the password for {{ .Email }}. The button below works once. If you didn't ask, ignore this email and your password stays the same.
Button:   Choose a new password
```

## What's in every email

Each email contains:

1. Your App name at the top.
2. The heading and message you wrote.
3. A button that links to your project's verify endpoint, which confirms the action and redirects to your app (see [Site URL and redirect URLs](/docs/auth/redirect-urls)).
4. "Or use this code", with the one-time code, so users can type it into your app with `verifyOtp` instead of clicking. See [Magic links and email OTP](/docs/auth/magic-links-otp).
5. The link as text, for mail clients that hide buttons.

## Change email confirmations

When a user changes their address with `updateUser({ email })`, the Change email template is used to confirm the change. Upstream Supabase Auth, by default, asks for confirmation from both the old and the new address before switching, so a hijacked session can't quietly move the account to an attacker's inbox. Tell users to look in both inboxes.

## Deliverability tips

- **Set a recognisable App name.** "Recipe Box" in the sender name is far less likely to be ignored than a project slug.
- **Keep the default structure.** One clear action per email, short text, no attachments.
- **Ask users to check spam** on your "check your email" screen, and offer a resend button with a cooldown.
- **Watch the limit** before bulk actions. Inviting 200 people from a script will run into the 30-email limit; spread invites out or send them yourself (below).

If emails don't arrive at all, work through [Not receiving Auth emails](/kb/not-receiving-auth-emails). If edits don't show, see [Email template changes not showing up](/kb/email-template-not-updating).

## Emails in several languages

There's one version of each template per project. To send in the user's language, see [Sending Auth emails in the user's language](/kb/custom-emails-by-language), which covers storing a language in user metadata and the approach below.

## When you need full control

For custom HTML, your own sender domain, or higher volume, send the emails yourself. The admin API can generate the same links Auth would email, without sending anything:

```ts
// Server only (Edge Function or backend) with the service_role key
const { data, error } = await admin.auth.admin.generateLink({
  type: 'magiclink',
  email: 'kim@example.com',
  options: { redirectTo: 'https://ledgerly.example.com/auth/callback' },
})

const link = data!.properties.action_link
const code = data!.properties.email_otp
// send `link` and `code` with Resend, Postmark, SendGrid...
```

`type` can be `signup`, `invite`, `magiclink`, `recovery`, `email_change_current` or `email_change_new`. Your app then calls your own endpoint instead of `signInWithOtp` or `resetPasswordForEmail`. See [Example: sending email](/docs/functions/sending-email) and [Email providers](/docs/integrations/resend).

The reauthentication email that Auth can send before sensitive changes isn't one of the editable templates.
