发送邮件钩子
使用自定义邮件提供商发送认证消息
发送邮件钩子在邮件发送前运行,为邮件发送提供了灵活性。您可以使用此钩子配置备用邮件提供商或为邮件添加国际化支持。
邮件发送行为
邮件发送取决于两个设置:邮件提供商和认证钩子状态。
邮件提供商 | 认证钩子 | 结果 |
---|---|---|
已启用 | 已启用 | 认证钩子处理邮件发送(不使用SMTP) |
已启用 | 已禁用 | SMTP处理邮件发送(如果配置了自定义SMTP则使用自定义,否则使用默认) |
已禁用 | 已启用 | 邮件注册功能禁用 |
已禁用 | 已禁用 | 邮件注册功能禁用 |
输入参数
字段 | 类型 | 描述 |
---|---|---|
user | User | 尝试登录的用户对象。 |
email | object | 邮件发送流程的元数据。包含一次性密码(OTP)和token_hash 。 |
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849{ "user": { "id": "8484b834-f29e-4af2-bf42-80644d154f76", "aud": "authenticated", "role": "authenticated", "email": "valid.email@supabase.io", "phone": "", "app_metadata": { "provider": "email", "providers": ["email"] }, "user_metadata": { "email": "valid.email@supabase.io", "email_verified": false, "phone_verified": false, "sub": "8484b834-f29e-4af2-bf42-80644d154f76" }, "identities": [ { "identity_id": "bc26d70b-517d-4826-bce4-413a5ff257e7", "id": "8484b834-f29e-4af2-bf42-80644d154f76", "user_id": "8484b834-f29e-4af2-bf42-80644d154f76", "identity_data": { "email": "valid.email@supabase.io", "email_verified": false, "phone_verified": false, "sub": "8484b834-f29e-4af2-bf42-80644d154f76" }, "provider": "email", "last_sign_in_at": "2024-05-14T12:56:33.824231484Z", "created_at": "2024-05-14T12:56:33.824261Z", "updated_at": "2024-05-14T12:56:33.824261Z", "email": "valid.email@supabase.io" } ], "created_at": "2024-05-14T12:56:33.821567Z", "updated_at": "2024-05-14T12:56:33.825595Z", "is_anonymous": false }, "email_data": { "token": "305805", "token_hash": "7d5b7b1964cf5d388340a7f04f1dbb5eeb6c7b52ef8270e1737a58d0", "redirect_to": "http://localhost:3000/", "email_action_type": "signup", "site_url": "http://localhost:9999", "token_new": "", "token_hash_new": "" }}
输出
- 不需要任何输出。返回状态码200的空响应即表示成功响应。
您可以通过"发送邮件"钩子配置Resend作为自定义邮件提供商。这使您能够利用Resend开发者友好的API发送邮件,并使用React Email管理邮件模板。如需更高级的React Email教程,请参考本指南。
如果想通过Supabase Resend集成(使用Resend的SMTP服务器)发送邮件,请查看此集成。
创建包含以下环境变量的.env文件:
12RESEND_API_KEY="your_resend_api_key"SEND_EMAIL_HOOK_SECRET="v1,whsec_<base64_secret>"
您可以在Supabase仪表板的Auth Hooks部分生成密钥。
在Supabase项目中设置密钥:
1supabase secrets set --env-file .env
创建新的边缘函数:
1supabase functions new send-email
将以下代码添加到边缘函数:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061import { Webhook } from "https://esm.sh/standardwebhooks@1.0.0";import { Resend } from "npm:resend";const resend = new Resend(Deno.env.get("RESEND_API_KEY") as string);const hookSecret = (Deno.env.get("SEND_EMAIL_HOOK_SECRET") as string).replace("v1,whsec_", "");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 } = 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 { error } = await resend.emails.send({ from: "welcome <onboarding@example.com>", to: [user.email], subject: "Welcome to my site!", text: `Confirm you signup with this code: ${email_data.token}`, }); if (error) { throw error; } } catch (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, });});
部署边缘函数并配置为钩子:
1supabase functions deploy send-email --no-verify-jwt