Auth

Send Email Hook

Use a custom email provider to send authentication messages


The Send Email Hook runs before an email is sent and allows for flexibility around email sending. You can use this hook to configure a back-up email provider or add internationalization to your emails.

Email sending behavior

Email sending depends on two settings: Email Provider and Auth Hook status.

Email ProviderAuth HookResult
EnabledEnabledAuth Hook handles email sending (SMTP not used)
EnabledDisabledSMTP handles email sending (custom if configured, default otherwise)
DisabledEnabledEmail Signups Disabled
DisabledDisabledEmail Signups Disabled

Inputs

FieldTypeDescription
userUserThe user attempting to sign in.
emailobjectMetadata specific to the email sending process. Includes the OTP and token_hash.

_49
{
_49
"user": {
_49
"id": "8484b834-f29e-4af2-bf42-80644d154f76",
_49
"aud": "authenticated",
_49
"role": "authenticated",
_49
"email": "valid.email@supabase.io",
_49
"phone": "",
_49
"app_metadata": {
_49
"provider": "email",
_49
"providers": ["email"]
_49
},
_49
"user_metadata": {
_49
"email": "valid.email@supabase.io",
_49
"email_verified": false,
_49
"phone_verified": false,
_49
"sub": "8484b834-f29e-4af2-bf42-80644d154f76"
_49
},
_49
"identities": [
_49
{
_49
"identity_id": "bc26d70b-517d-4826-bce4-413a5ff257e7",
_49
"id": "8484b834-f29e-4af2-bf42-80644d154f76",
_49
"user_id": "8484b834-f29e-4af2-bf42-80644d154f76",
_49
"identity_data": {
_49
"email": "valid.email@supabase.io",
_49
"email_verified": false,
_49
"phone_verified": false,
_49
"sub": "8484b834-f29e-4af2-bf42-80644d154f76"
_49
},
_49
"provider": "email",
_49
"last_sign_in_at": "2024-05-14T12:56:33.824231484Z",
_49
"created_at": "2024-05-14T12:56:33.824261Z",
_49
"updated_at": "2024-05-14T12:56:33.824261Z",
_49
"email": "valid.email@supabase.io"
_49
}
_49
],
_49
"created_at": "2024-05-14T12:56:33.821567Z",
_49
"updated_at": "2024-05-14T12:56:33.825595Z",
_49
"is_anonymous": false
_49
},
_49
"email_data": {
_49
"token": "305805",
_49
"token_hash": "7d5b7b1964cf5d388340a7f04f1dbb5eeb6c7b52ef8270e1737a58d0",
_49
"redirect_to": "http://localhost:3000/",
_49
"email_action_type": "signup",
_49
"site_url": "http://localhost:9999",
_49
"token_new": "",
_49
"token_hash_new": ""
_49
}
_49
}

Outputs

  • No outputs are required. An empty response with a status code of 200 is taken as a successful response.

You can configure Resend as the custom email provider through the "Send Email" hook. This allows you to take advantage of Resend's developer-friendly APIs to send emails and leverage React Email for managing your email templates. For a more advanced React Email tutorial, refer to this guide.

If you want to send emails through the Supabase Resend integration, which uses Resend's SMTP server, check out this integration instead.

Create a .env file with the following environment variables:


_10
RESEND_API_KEY=your_resend_api_key
_10
SEND_EMAIL_HOOK_SECRET=<base64_secret>

Set the secrets in your Supabase project:


_10
supabase secrets set --env-file .env

Create a new edge function:


_10
supabase functions new send-email

Add the following code to your edge function:


_61
import { Webhook } from "https://esm.sh/standardwebhooks@1.0.0";
_61
import { Resend } from "npm:resend";
_61
_61
const resend = new Resend(Deno.env.get("RESEND_API_KEY") as string);
_61
const hookSecret = Deno.env.get("SEND_EMAIL_HOOK_SECRET") as string;
_61
_61
Deno.serve(async (req) => {
_61
if (req.method !== "POST") {
_61
return new Response("not allowed", { status: 400 });
_61
}
_61
_61
const payload = await req.text();
_61
const headers = Object.fromEntries(req.headers);
_61
const wh = new Webhook(hookSecret);
_61
try {
_61
const { user, email_data } = wh.verify(payload, headers) as {
_61
user: {
_61
email: string;
_61
};
_61
email_data: {
_61
token: string;
_61
token_hash: string;
_61
redirect_to: string;
_61
email_action_type: string;
_61
site_url: string;
_61
token_new: string;
_61
token_hash_new: string;
_61
};
_61
};
_61
_61
const { error } = await resend.emails.send({
_61
from: "welcome <onboarding@example.com>",
_61
to: [user.email],
_61
subject: "Welcome to my site!",
_61
text: `Confirm you signup with this code: ${email_data.token}`,
_61
});
_61
if (error) {
_61
throw error;
_61
}
_61
} catch (error) {
_61
return new Response(
_61
JSON.stringify({
_61
error: {
_61
http_code: error.code,
_61
message: error.message,
_61
},
_61
}),
_61
{
_61
status: 401,
_61
headers: { "Content-Type": "application/json" },
_61
},
_61
);
_61
}
_61
_61
const responseHeaders = new Headers();
_61
responseHeaders.set("Content-Type", "application/json");
_61
return new Response(JSON.stringify({}), {
_61
status: 200,
_61
headers: responseHeaders,
_61
});
_61
});

Deploy your edge function and configure it as a hook:


_10
supabase functions deploy send-email --no-verify-jwt