使用Supabase Edge功能,PostgreSQL创建自定义的I18N准备就绪的身份验证电子邮件,然后重新启动
#网络开发人员 #database #authentication #i18n

欢迎来到另一个激动人心的教程,以构建强大的应用程序!如今,我们正在深入研究Supabase的世界,Supabase是一种开源后端解决方案,它为开发人员提供了一个强大的工具包来创建可扩展应用程序。在本指南中,我们将探讨如何利用Supabase Edge Functions,PostgreSQL和重新发送电子邮件服务来制作个性化身份验证电子邮件系统。

介绍

随着对高效后端解决方案的需求不断增长,Supabase已成为改变游戏规则的人。 Supabase提供实时订阅,身份验证和数据库管理等功能,简化了复杂的后端任务。但是,一个独特的挑战在于自定义电子邮件模板以进行用户参与。在我们以前关于Exploring Data Relationships with Supabase and PostgreSQL的博客文章中,我们深入研究了数据关系的复杂性。在该基金会的基础上,我们现在应对创建个性化身份验证电子邮件系统的挑战,该系统也无缝支持I18N本地化。

I18N本地化在电子邮件中的意义

在当今的全球景观中,迎合不同观众的迎合对于增强用户参与至关重要。国际化(I18N)确保电子邮件在各种文化和语言中引起用户的共鸣。通过基于用户的首选语言动态替换内容,我们不仅可以增强用户体验,还可以增强包容性感。

先决条件

在我们深入研究技术复杂性之前,必须熟悉Supabase,PostgreSQL,并在必要时可以掌握DeNo的基础知识。设置开发环境,安装基本工具以及基于操作系统配置依赖项将为成功实施建立坚实的基础。

建立坚实的数据库基础

我们的旅程始于建立强大的数据库基金会。这涉及在内部架构中创建email_templates表。该表用作关键存储库,存储重要信息,例如主题行,内容,语言和模板类型。

CREATE SCHEMA internal;

CREATE TABLE internal.email_templates (
  id BIGINT GENERATED BY DEFAULT AS IDENTITY,
  subject TEXT NULL,
  content TEXT NULL,
  email_language TEXT NULL,
  email_type TEXT NULL,
  CONSTRAINT email_templates_pkey PRIMARY KEY (id)
);

通过制定这一强大的基础,我们为动态和多功能的电子邮件系统奠定了基础。该系统将由即将发布的get_email_template函数供电,我们将在以下各节中进行探索。

制作动态get_email_template功能

我们电子邮件系统的核心位于get_email_template功能中。此动态功能会检索电子邮件模板,并利用输入(例如模板类型,链接和语言)。重要的是,该功能与email_templates表无缝集成,提供个性化的电子邮件内容。

CREATE OR REPLACE FUNCTION get_email_template(
  template_type TEXT,
  link TEXT,
  language TEXT DEFAULT 'en'
)
RETURNS JSON
SECURITY DEFINER
SET search_path = public, internal AS
$BODY$
DECLARE
  email_subject TEXT;
  email_content TEXT;
  email_json JSON;
BEGIN
  SELECT subject, REPLACE(content, '{{LINK}}', link) INTO email_subject, email_content
  FROM internal.email_templates
  WHERE email_type = template_type AND email_language = language;
  email_json := json_build_object('subject', email_subject, 'content', email_content);
  RETURN email_json;
END;
$BODY$
LANGUAGE plpgsql;
-- Protect this function to be only available to service_role key:
REVOKE EXECUTE ON FUNCTION get_email_template FROM anon, authenticated;

为常见身份验证方案定制电子邮件模板

为了增强用户体验和参与度,我们将定制几种常见身份验证方案的电子邮件模板:密码恢复,注册确认,邀请和魔术链接。

这些模板将以三种语言提供:葡萄牙语,英语和丹麦语。您可以将这些模板无缝集成到内部模式中的email_templates表中。下面,您会找到每种情况的模板:

--
-- Data for Name: email_templates; Type: TABLE DATA; Schema: internal; Owner: postgres
--

INSERT INTO "internal"."email_templates" ("id", "subject", "content", "email_language", "email_type") VALUES
    (1, 'Din Magisk Link', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<html lang="da">
<head></head>
<body style="background-color:#ffffff;font-family:-apple-system,BlinkMacSystemFont,&quot;Segoe UI&quot;,Roboto,Oxygen-Sans,Ubuntu,Cantarell,&quot;Helvetica Neue&quot;,sans-serif">
    <table align="center" role="presentation" cellSpacing="0" cellPadding="0" border="0" width="100%" style="max-width:37.5em;margin:0 auto;padding:20px 25px 48px;background-image:url(&quot;/assets/background-image.png&quot;);background-position:bottom;background-repeat:no-repeat, no-repeat">
        <tr style="width:100%">
            <td>
                <h1 style="font-size:28px;font-weight:bold;margin-top:48px">🪄 Din magiske link</h1>
                <table style="margin:24px 0" align="center" border="0" cellPadding="0" cellSpacing="0" role="presentation" width="100%">
                    <tbody>
                        <tr>
                            <td>
                                <p style="font-size:16px;line-height:26px;margin:16px 0"><a target="_blank" style="color:#FF6363;text-decoration:none" href="{{LINK}}">👉 Klik her for at logge ind 👈</a></p>
                                <p style="font-size:16px;line-height:26px;margin:16px 0">Hvis du ikke har anmodet om dette, bedes du ignorere denne e-mail.</p>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <p style="font-size:16px;line-height:26px;margin:16px 0">Bedste hilsner,<br />- Contoso Team</p>
                <hr style="width:100%;border:none;border-top:1px solid #eaeaea;border-color:#dddddd;margin-top:48px" />
                <p style="font-size:12px;line-height:24px;margin:16px 0;color:#8898aa;margin-left:4px">Contoso Technologies Inc.</p>
            </td>
        </tr>
    </table>
</body>
</html>
', 'da', 'magiclink');

-- Check the full SQL file and all templates in the GitHub repo
-- https://github.com/mansueli/Supabase-Edge-AuthMailer

通过以多种语言为这些方案提供量身定制的模板,您可以确保电子邮件通信会引起更大的受众共鸣。这种个性化促进了更强的用户参与和互动。

开发DENO EDGE功能(index.ts)

在接下来的部分中,我们将深入研究DENO EDGE功能的开发过程,负责管理身份验证电子邮件请求。下面,我们将概述此过程中涉及的关键步骤:

  1. 初始化进口和常数:我们将通过导入基本模块并设置将有助于无缝开发过程的常数开始。

  2. 创建一个安全的supabase客户端:学习如何使用管理凭据建立与Supabase的安全连接,以确保授权访问所需的资源。

  3. 处理传入的HTTP请求:发现serve功能的利用来有效处理传入的HTTP请求,增强了系统的整体响应能力。

  4. 提取重要参数:了解从传入请求中提取关键参数的过程,例如电子邮件,身份验证类型,语言,密码和重定向URL。

  5. 生成安全的身份验证链接:使用Supabase Admin API探索生成安全的身份验证链接所涉及的步骤,从而促进安全的用户交互。

  6. 自定义重定向链接:学习如何自定义重定向链接以匹配特定要求并提高用户体验。

  7. 调用 get_email_template函数:潜入supabase rpc方法的使用来调用get_email_template函数,从而无缝地检索电子邮件内容。

  8. 重新启动API集成:了解重新启动API的无缝集成,允许向用户发送个性化和信息丰富的电子邮件。

有关DENO EDGE功能的完整代码,请参阅提供的index.ts文件。

// Importing required libraries
import { serve } from 'https://deno.land/std@0.192.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

// Defining CORS headers
export const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}

// Log to indicate the function is up and running
console.log(`Function "auth-mailer" up and running!`)

// Creating a Supabase client using environment variables
const supabaseAdmin = createClient(
  Deno.env.get('SUPABASE_URL') ?? '',
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
)

// Define a server that handles different types of requests
serve(async (req: Request) => {
  // Handling preflight CORS requests
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  try {
    // Destructuring request JSON and setting default values
    let { email, type, language = 'en', password = '', redirect_to = '' } = await req.json();
    console.log(JSON.stringify({ email, type, language, password }, null, 2));

    // Generate a link with admin API call
    let linkPayload: any = {
      type,
      email,
    }

    // If type is 'signup', add password to the payload
    if (type == 'signup') {
      linkPayload = {
        ...linkPayload,
        password,
      }
      console.log("linkPayload", linkPayload);
    }

    // Generate the link
    const { data: linkResponse, error: linkError } = await supabaseAdmin.auth.admin.generateLink(linkPayload)
    console.log("linkResponse", linkResponse);

    // Throw error if any occurs during link generation
    if (linkError) {
      throw linkError;
    }

    // Getting the actual link and manipulating the redirect link
    let actual_link = linkResponse.properties.action_link;
    if (redirect_to != '') {
      actual_link = actual_link.split('redirect_to=')[0];
      actual_link = actual_link + '&redirect_to=' + redirect_to;
    }

    // Log the template data
    console.log(JSON.stringify({ "template_type":type, "link": linkResponse, "language":language }, null, 2));

    // Get the email template
    const { data: templateData, error: templateError } = await supabaseAdmin.rpc('get_email_template', { "template_type":type, "link": actual_link, "language":language });

    // Throw error if any occurs during template fetching
    if (templateError) {
      throw templateError;
    }

    // Send the email using resend
    const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY')
    const resendRes = await fetch('https://api.resend.com/emails', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${RESEND_API_KEY}`,
      },
      body: JSON.stringify({
        from: 'rodrigo@mansueli.com',
        to: email,
        subject: templateData.subject,
        html: templateData.content,
      }),
    });

    // Handle the response from the resend request
    const resendData = await resendRes.json();
    return new Response(JSON.stringify(resendData), {
      status: resendRes.status,
      headers: {
        'Content-Type': 'application/json',
      },
    })
  } catch (error) {
    // Handle any other errors
    return new Response(JSON.stringify({ error: error.message }), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' },
      status: 400,
    })
  }
})

地址supabase电子邮件模板行为

处理电子邮件模板时,必须确认supabase的特定行为。默认情况下,Supabase使用平台的默认模板时,将从电子邮件模板中删除HTML标签。我们在此提出的方法使您可以对电子邮件内容的可视化呈现进行控制。要有效地在电子邮件模板中包括HTML元素,您可以遵守标准HTML实践。

结论和未来的增强

祝贺使用Supabase Edge功能,PostgreSQL和Resent Service成功构建个性化身份验证电子邮件系统。通过利用Supabase的功能,您已经简化了向用户发送量身定制的验证电子邮件的过程。

本教程涵盖了基本方面,但总有增长的余地。考虑扩展电子邮件模板自定义的范围或集成其他第三方服务以提高用户参与度。当您继续探索Supabase的功能时,与开源社区分享您的见解和增强。

您可以在GitHub上找到本文中使用的完整代码。

进一步学习资源

对于其他学习,我们建议探索以下资源: