أضف إشعارات البريد الإلكتروني إلى موقع الحجوزات الذكي

أرسل رسائل تأكيد الحجز وتنبيهات المالك باستخدام Supabase وResend وEdge Functions.

خارطة الطريق والموارد

جديد هنا؟ ابدأ من هنا أولًا

يُرقّي هذا الدليل مشروع موقع الحجوزات الذكي بإشعارات بريد إلكتروني تلقائية. إذا لم تكن قد بنيت موقع الحجوزات بعد، فابدأ بالدليل الرئيسي أولًا.

ابنِ موقع حجوزات بالذكاء الاصطناعي

افتح الدليل الرئيسي

MAIN GUIDE

https://profitstudio.app/video/build-booking-website-ai

أعد Resend لرسائل بريد الحجوزات

أنشئ حساب Resend واضبط إعداداته

افتح Resend

https://resend.com/

أنشئ حساب Resend ولّد مفتاح Resend API انسخ المفتاح واحفظه في مكان آمن

مهم

احتفظ بمفتاح Resend API سريًا. لا تضعه أبدًا في كود الواجهة الأمامية ولا تشاركه علنًا.

أضف نطاق الإرسال وتحقق منه

أضف نطاق موقع الحجز الخاص بك اختر أقرب منطقة انسخ سجلات DNS من Resend أضف السجلات لدى مزود النطاق ارجع إلى Resend وتأكد من التحقق من النطاق

قد يستغرق التحقق من DNS بضع دقائق أو أكثر حسب مزود النطاق الذي تستخدمه.

أنشئ دالة بريد الحجوزات

أنشئ Edge Function الخاصة ببريد الحجز

افتح Supabase

https://supabase.com/?utm_source=partner&utm_medium=social&utm_campaign=supasquad&dub_id=faVfKdcLWvKCbYNp

افتح مشروع Supabase الخاص بك افتح Edge Functions أنشئ دالة جديدة باستخدام محرر المتصفح سمِّ الدالة `send-booking-email` احذف الكود الافتراضي المبدئي

خصّص كود الدالة وأضفه

أدخل البريد الإلكتروني للمالك أدخل نطاق Resend الذي تم التحقق منه أدخل اسم النشاط التجاري المرسِل خصّص قوالب البريد الإلكتروني عند الحاجة انسخ كود الدالة الناتج والصقه

دالة بريد الحجوزات

import { serve } from "https://deno.land/std/http/server.ts"; serve(async (req) => { try { const body = await req.json(); const record = body.record || {}; const resendKey = Deno.env.get("RESEND_API_KEY"); const supabaseUrl = Deno.env.get("SUPABASE_URL"); const supabaseServiceRoleKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"); if (!resendKey) { return new Response( JSON.stringify({ error: "Missing RESEND_API_KEY secret" }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } const ownerEmail = "YOUR_OWNER_EMAIL"; const customerEmail = record.email || ""; const customerName = record.full_name || record.name || "Customer"; const phone = record.phone || ""; const appointmentDate = record.appointment_date || record.date || ""; const startTime = record.start_time || record.time || ""; const endTime = record.end_time || ""; const notes = record.notes || ""; const status = record.status || "New"; let serviceName = record.service_name || record.service || record.service_title || ""; // If the appointment only has service_id, fetch the service name from the services table if (!serviceName && record.service_id && supabaseUrl && supabaseServiceRoleKey) { try { const serviceId = encodeURIComponent(record.service_id); const serviceResponse = await fetch( `${supabaseUrl}/rest/v1/services?id=eq.${serviceId}&select=name`, { method: "GET", headers: { apikey: supabaseServiceRoleKey, Authorization: `Bearer ${supabaseServiceRoleKey}`, "Content-Type": "application/json", }, } ); const serviceData = await serviceResponse.json(); if (Array.isArray(serviceData) && serviceData.length > 0) { serviceName = serviceData[0].name || ""; } } catch (_serviceError) { serviceName = ""; } } if (!serviceName) { serviceName = "Appointment"; } // 1) Email to business owner const ownerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "Bookings <bookings@YOUR_DOMAIN_NAME>", to: [ownerEmail], subject: "OWNER_NOTIFICATION_SUBJECT", html: ` <h2>OWNER_NOTIFICATION_HEADING</h2> <p>OWNER_NOTIFICATION_INTRO</p> <p><b>Customer Name:</b> ${customerName}</p> <p><b>Email:</b> ${customerEmail}</p> <p><b>Phone:</b> ${phone}</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p><b>Notes:</b> ${notes}</p> <p><b>Status:</b> ${status}</p> `, }), }); const ownerData = await ownerResponse.json(); // 2) Email to customer let customerData = null; if (customerEmail) { const customerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "YOUR_BUSINESS_NAME <bookings@YOUR_DOMAIN_NAME>", to: [customerEmail], subject: "CUSTOMER_CONFIRMATION_SUBJECT", html: ` <h2>CUSTOMER_CONFIRMATION_HEADING</h2> <p>Hi ${customerName},</p> <p>CUSTOMER_CONFIRMATION_INTRO</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p>If you need to make any changes, please contact us before your appointment.</p> <p>CUSTOMER_CONFIRMATION_CLOSING</p> `, }), }); customerData = await customerResponse.json(); } return new Response( JSON.stringify({ success: true, ownerEmailSent: ownerData, customerEmailSent: customerData, }), { headers: { "Content-Type": "application/json" }, } ); } catch (error) { return new Response( JSON.stringify({ success: false, error: String(error), }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } });

بريد المالك

owner@example.com

نطاق Resend موثّق

yourdomain.com

اسم العمل المرسل

عيادة برايت لطب الأسنان

موضوع بريد المالك

عنوان بريد المالك

نص مقدمة بريد المالك

موضوع بريد الزبون

عنوان بريد الزبون

نص مقدمة بريد الزبون

نص خاتمة بريد الزبون

انشر الدالة واضبط إعداداتها

انشر الدالة افتح إعدادات الدالة عطّل `Verify JWT With Legacy Secret` احفظ التغييرات انسخ رابط endpoint الخاص بالدالة واحفظه لإعداد Webhook

مهم

عطّل خيار “Verify JWT With Legacy Secret” حتى يتمكن Database Webhook من استدعاء الدالة.

أضف مفتاح Resend API إلى Supabase

أضف مفتاح Resend API كسر في Supabase

افتح Edge Function Secrets أنشئ سرًا جديدًا اضبط الاسم على `RESEND_API_KEY` الصق مفتاح Resend API احفظ السر

مهم

استخدم اسم السر بالضبط `RESEND_API_KEY`. أي خطأ إملائي سيمنع الدالة من الوصول إلى Resend.

اربط البريد الإلكتروني بالحجوزات الجديدة

أنشئ Webhook الخاص ببريد الحجز

شغّل دالة بريد الحجز في كل مرة يُضاف فيها موعد جديد.

Integrations Database Webhooks

افتح Database Webhooks فعّل Database Webhooks أنشئ webhook جديدًا سمِّه `send-booking-email-webhook` اختر جدول `public.appointments` اختر `Insert` كحدث أبقِ النوع على `HTTP Request` استخدم `POST` كطريقة للطلب الصق رابط endpoint الخاص بـ Edge Function أنشئ الـ webhook

اختبر نظام بريد الحجوزات

اختبر مسار بريد الحجز بالكامل

اختبر مسار الحجز بالكامل وتأكد من وصول كلا البريدين بشكل صحيح.

افتح موقع الحجز المباشر أرسل موعدًا تجريبيًا تأكد من حفظ الحجز في Supabase تحقق من بريد التأكيد المرسل إلى العميل تحقق من بريد الإشعار المرسل إلى المالك تأكد من صحة تفاصيل الحجز في كلا البريدين تأكد من ظهور الحجز في لوحة تحكم المشرف