You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Supabase谷歌登录场景下给首次登录用户发送邮件?

Supabase谷歌登录首次用户提示邮件实现方案

方案一:数据库触发器 + Supabase Edge Functions(推荐,后端自动处理)

这种方案无需客户端介入,完全在Supabase生态内完成,可靠性更高,避免客户端逻辑遗漏。

  1. 创建用户扩展表(可选但推荐)
    为了跟踪邮件发送状态,建议创建一个profiles表关联auth.users:

    CREATE TABLE profiles (
      user_id UUID REFERENCES auth.users(id) PRIMARY KEY,
      email TEXT UNIQUE NOT NULL,
      welcome_email_sent BOOLEAN DEFAULT false,
      created_at TIMESTAMP WITH TIME ZONE DEFAULT TIME ZONE 'utc'::text NOT NULL
    );
    
  2. 编写发送邮件的Edge Function
    创建一个Edge Function来处理邮件发送逻辑,支持幂等性(避免重复发送):

    import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
    import { sendMail } from 'https://esm.sh/deno-mailer'
    
    Deno.serve(async (req) => {
      const supabaseAdmin = createClient(
        Deno.env.get('SUPABASE_URL')!,
        Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
      )
    
      const { record } = await req.json()
      const userId = record.id
      const userEmail = record.email
    
      // 检查是否已发送过欢迎邮件
      const { data: profile } = await supabaseAdmin
        .from('profiles')
        .select('welcome_email_sent')
        .eq('user_id', userId)
        .single()
    
      if (profile?.welcome_email_sent) {
        return new Response(JSON.stringify({ status: 'already sent' }), { status: 200 })
      }
    
      // 发送欢迎邮件
      try {
        await sendMail({
          from: '你的应用 <support@yourapp.com>',
          to: userEmail,
          subject: '欢迎加入我们的应用!',
          html: '<p>感谢您首次登录,这是为您准备的提示内容...</p>'
        })
    
        // 更新状态标记邮件已发送
        await supabaseAdmin
          .from('profiles')
          .update({ welcome_email_sent: true })
          .eq('user_id', userId)
    
        return new Response(JSON.stringify({ status: 'success' }), { status: 200 })
      } catch (err) {
        return new Response(JSON.stringify({ error: err.message }), { status: 500 })
      }
    })
    
  3. 创建数据库触发器
    监听auth.users表的INSERT事件,触发Edge Function:

    CREATE OR REPLACE FUNCTION trigger_welcome_email()
    RETURNS TRIGGER AS $$
    BEGIN
      -- 先初始化profiles记录(避免冲突)
      INSERT INTO profiles (user_id, email)
      VALUES (NEW.id, NEW.email)
      ON CONFLICT (user_id) DO NOTHING;
    
      -- 调用Edge Function
      PERFORM http_post(
        'https://<你的项目ID>.supabase.co/functions/v1/send-welcome-email',
        json_build_object('record', NEW)::text,
        'application/json',
        ARRAY[('Authorization', 'Bearer ' || current_setting('supabase.service_role_key'))]
      );
      RETURN NEW;
    END;
    $$ LANGUAGE plpgsql SECURITY DEFINER;
    
    CREATE TRIGGER on_new_user_created
    AFTER INSERT ON auth.users
    FOR EACH ROW EXECUTE FUNCTION trigger_welcome_email();
    

方案二:客户端判断 + 后端邮件接口

如果需要在客户端做额外逻辑(比如引导用户完成资料填写后再发邮件),可以用这种方案:

  1. 登录后判断是否为首次用户
    用户完成谷歌登录后,查询自定义的profiles表,若不存在记录则判定为首次登录:

    async function handleGoogleLogin() {
      const { error } = await supabase.auth.signInWithOAuth({ provider: 'google' });
      if (error) return;
    
      const { data: { user } } = await supabase.auth.getUser();
      if (!user) return;
    
      // 查询用户是否存在于profiles表
      const { data: profile, error: profileErr } = await supabase
        .from('profiles')
        .select('id')
        .eq('user_id', user.id)
        .single();
    
      // 若不存在则是首次登录
      if (profileErr && profileErr.code === 'PGRST116') {
        // 调用邮件接口发送提示
        await fetch('/api/send-welcome-email', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ email: user.email, userId: user.id })
        });
    
        // 创建profiles记录
        await supabase.from('profiles').insert({ user_id: user.id, email: user.email });
      }
    }
    
  2. 后端邮件接口实现
    用你熟悉的后端框架(比如Node.js/Express)实现邮件发送接口,同样要处理幂等性:

    // Express示例
    app.post('/api/send-welcome-email', async (req, res) => {
      const { email, userId } = req.body;
      const supabaseAdmin = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY);
    
      // 检查邮件是否已发送
      const { data: profile } = await supabaseAdmin
        .from('profiles')
        .select('welcome_email_sent')
        .eq('user_id', userId)
        .single();
    
      if (profile?.welcome_email_sent) {
        return res.status(200).json({ status: 'already sent' });
      }
    
      // 发送邮件(用你选择的邮件服务,比如Nodemailer)
      await transporter.sendMail({
        from: '你的应用 <support@yourapp.com>',
        to: email,
        subject: '欢迎首次登录!',
        text: '这是给您的提示邮件内容...'
      });
    
      // 更新状态
      await supabaseAdmin
        .from('profiles')
        .update({ welcome_email_sent: true })
        .eq('user_id', userId);
    
      res.status(200).json({ status: 'success' });
    });
    

注意事项

  • 幂等性:必须添加邮件发送状态标记,避免因触发器重复触发或客户端重复请求导致多次发送邮件。
  • 环境变量:邮件服务密钥、Supabase的服务角色密钥等敏感信息要存在环境变量中,禁止硬编码。
  • 测试:先用Supabase本地开发环境测试触发器和Edge Function,确保逻辑正常后再部署到生产环境。

内容的提问来源于stack exchange,提问作者Eran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 09:51:23