---
title: 'Custom Auth Emails with React Email and Resend'
description: 'Use the send email hook to send custom auth emails with React Email and Resend in Supabase Edge Functions.'
tocVideo: 'tlA7BomSCgU'
---
Use the [send email hook](/docs/guides/auth/auth-hooks/send-email-hook?queryGroups=language&language=http) to send custom auth emails with [React Email](https://react.email/) and [Resend](https://resend.com/) in Supabase Edge Functions.
Prefer to jump straight to the code? [Check out the example on GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/auth-hook-react-email-resend).
### Prerequisites
To get the most out of this guide, you’ll need to:
- [Create a Resend API key](https://resend.com/api-keys)
- [Verify your domain](https://resend.com/domains)
Make sure you have the latest version of the [Supabase CLI](https://supabase.com/docs/guides/cli#installation) installed.
### 1. Create Supabase function
Create a new function locally:
```bash
supabase functions new send-email
```
### 2. Edit the handler function
Paste the following code into the `index.ts` file:
```tsx supabase/functions/send-email/index.ts
import React from 'npm:react@18.3.1'
import { Webhook } from 'https://esm.sh/standardwebhooks@1.0.0'
import { Resend } from 'npm:resend@4.0.0'
import { renderAsync } from 'npm:@react-email/components@0.0.22'
import { MagicLinkEmail } from './_templates/magic-link.tsx'
const resend = new Resend(Deno.env.get('RESEND_API_KEY') as string)
const hookSecret = Deno.env.get('SEND_EMAIL_HOOK_SECRET') as string
Deno.serve(async (req) => {
if (req.method !== 'POST') {
return new Response('not allowed', { status: 400 })
}
const payload = await req.text()
const headers = Object.fromEntries(req.headers)
const wh = new Webhook(hookSecret)
try {
const {
user,
email_data: { token, token_hash, redirect_to, email_action_type },
} = wh.verify(payload, headers) as {
user: {
email: string
}
email_data: {
token: string
token_hash: string
redirect_to: string
email_action_type: string
site_url: string
token_new: string
token_hash_new: string
}
}
const html = await renderAsync(
React.createElement(MagicLinkEmail, {
supabase_url: Deno.env.get('SUPABASE_URL') ?? '',
token,
token_hash,
redirect_to,
email_action_type,
})
)
const { error } = await resend.emails.send({
from: 'welcome ',
to: [user.email],
subject: 'Supa Custom MagicLink!',
html,
})
if (error) {
throw error
}
} catch (error) {
console.log(error)
return new Response(
JSON.stringify({
error: {
http_code: error.code,
message: error.message,
},
}),
{
status: 401,
headers: { 'Content-Type': 'application/json' },
}
)
}
const responseHeaders = new Headers()
responseHeaders.set('Content-Type', 'application/json')
return new Response(JSON.stringify({}), {
status: 200,
headers: responseHeaders,
})
})
```
### 3. Create React Email Templates
Create a new folder `_templates` and create a new file `magic-link.tsx` with the following code:
```tsx supabase/functions/send-email/_templates/magic-link.tsx
import {
Body,
Container,
Head,
Heading,
Html,
Link,
Preview,
Text,
} from 'npm:@react-email/components@0.0.22'
import * as React from 'npm:react@18.3.1'
interface MagicLinkEmailProps {
supabase_url: string
email_action_type: string
redirect_to: string
token_hash: string
token: string
}
export const MagicLinkEmail = ({
token,
supabase_url,
email_action_type,
redirect_to,
token_hash,
}: MagicLinkEmailProps) => (
Log in with this magic link
Login
Click here to log in with this magic link
Or, copy and paste this temporary login code:
{token}
If you didn't try to login, you can safely ignore this email.
ACME Corp
, the famouse demo corp.
)
export default MagicLinkEmail
const main = {
backgroundColor: '#ffffff',
}
const container = {
paddingLeft: '12px',
paddingRight: '12px',
margin: '0 auto',
}
const h1 = {
color: '#333',
fontFamily:
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
fontSize: '24px',
fontWeight: 'bold',
margin: '40px 0',
padding: '0',
}
const link = {
color: '#2754C5',
fontFamily:
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
fontSize: '14px',
textDecoration: 'underline',
}
const text = {
color: '#333',
fontFamily:
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
fontSize: '14px',
margin: '24px 0',
}
const footer = {
color: '#898989',
fontFamily:
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
fontSize: '12px',
lineHeight: '22px',
marginTop: '12px',
marginBottom: '24px',
}
const code = {
display: 'inline-block',
padding: '16px 4.5%',
width: '90.5%',
backgroundColor: '#f4f4f4',
borderRadius: '5px',
border: '1px solid #eee',
color: '#333',
}
```
You can find a selection of React Email templates in the [React Email Eamples](https://react.email/examples).
### 4. Deploy the Function
Deploy function to Supabase:
```bash
supabase functions deploy send-email --no-verify-jwt
```
Note down the function URL, you will need it in the next step!
### 5. Configure the Send Email Hook
- Go to the [Auth Hooks](/dashboard/project/_/auth/hooks) section of the Supabase dashboard and create a new "Send Email hook".
- Select HTTPS as the hook type.
- Paste the function URL in the "URL" field.
- Click "Generate Secret" to generate your webhook secret and note it down.
- Click "Create" to save the hook configuration.
Store these secrets in your `.env` file.
```bash supabase/functions/.env
RESEND_API_KEY=your_resend_api_key
SEND_EMAIL_HOOK_SECRET=
```
You can generate the secret in the [Auth Hooks](/dashboard/project/_/auth/hooks) section of the Supabase dashboard. Make sure to remove the `v1,whsec_` prefix!
Set the secrets from the `.env` file:
```bash
supabase secrets set --env-file supabase/functions/.env
```
That's it, now your Supabase Edge Function will be triggered anytime an Auth Email needs to be send to the user!
## More Resources
- [Send Email Hooks](/docs/guides/auth/auth-hooks/send-email-hook)
- [Auth Hooks](/docs/guides/auth/auth-hooks)