120 lines
4.8 KiB
TypeScript
120 lines
4.8 KiB
TypeScript
import { serve } from "https://deno.land/std@0.192.0/http/server.ts";
|
|
|
|
serve(async (req) => {
|
|
// ✅ CORS preflight
|
|
if (req?.method === "OPTIONS") {
|
|
return new Response("ok", {
|
|
headers: {
|
|
"Access-Control-Allow-Origin": "*",
|
|
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
"Access-Control-Allow-Headers": "*",
|
|
},
|
|
});
|
|
}
|
|
|
|
try {
|
|
const { email, inviterName, role, token, message, siteUrl } = await req?.json();
|
|
|
|
const RESEND_API_KEY = Deno?.env?.get("RESEND_API_KEY");
|
|
if (!RESEND_API_KEY) {
|
|
throw new Error("RESEND_API_KEY is not set");
|
|
}
|
|
|
|
const acceptUrl = `${siteUrl || "https://broadcastb5322.builtwithrocket.new"}/invite/accept?token=${token}`;
|
|
|
|
const roleLabel = role === "editor" ? "Editor" : role === "admin" ? "Administrator" : "Contributor";
|
|
|
|
const htmlBody = `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
</head>
|
|
<body style="margin:0;padding:0;background:#0d1117;font-family:Arial,sans-serif;">
|
|
<table width="100%" cellpadding="0" cellspacing="0" style="background:#0d1117;padding:40px 20px;">
|
|
<tr>
|
|
<td align="center">
|
|
<table width="600" cellpadding="0" cellspacing="0" style="background:#111827;border-radius:8px;overflow:hidden;border:1px solid #1f2937;">
|
|
<tr>
|
|
<td style="background:#1a2535;padding:24px 32px;border-bottom:1px solid #2a3a50;">
|
|
<p style="margin:0;color:#3b82f6;font-size:13px;font-weight:700;letter-spacing:2px;text-transform:uppercase;">BroadcastBeat</p>
|
|
<p style="margin:4px 0 0;color:#9ca3af;font-size:12px;">Digital Platform for Broadcast Engineering</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding:32px;">
|
|
<h1 style="margin:0 0 16px;color:#f9fafb;font-size:22px;font-weight:700;">You've been invited to contribute</h1>
|
|
<p style="margin:0 0 16px;color:#9ca3af;font-size:15px;line-height:1.6;">
|
|
${inviterName || "A BroadcastBeat administrator"} has invited you to join BroadcastBeat as a <strong style="color:#3b82f6;">${roleLabel}</strong>.
|
|
</p>
|
|
${message ? `<div style="background:#1f2937;border-left:3px solid #3b82f6;padding:12px 16px;border-radius:4px;margin:0 0 24px;">
|
|
<p style="margin:0;color:#d1d5db;font-size:14px;font-style:italic;">"${message}"</p>
|
|
</div>` : ""}
|
|
<p style="margin:0 0 24px;color:#9ca3af;font-size:14px;line-height:1.6;">
|
|
As a ${roleLabel}, you'll be able to submit articles for publication on our platform. Click the button below to accept your invitation and set up your account.
|
|
</p>
|
|
<table cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td style="background:#3b82f6;border-radius:6px;">
|
|
<a href="${acceptUrl}" style="display:inline-block;padding:12px 28px;color:#ffffff;font-size:14px;font-weight:700;text-decoration:none;letter-spacing:0.5px;">Accept Invitation</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<p style="margin:24px 0 0;color:#6b7280;font-size:12px;">
|
|
This invitation expires in 7 days. If you did not expect this invitation, you can safely ignore this email.
|
|
</p>
|
|
<p style="margin:12px 0 0;color:#4b5563;font-size:11px;word-break:break-all;">
|
|
Or copy this link: ${acceptUrl}
|
|
</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="background:#0d1117;padding:16px 32px;border-top:1px solid #1f2937;">
|
|
<p style="margin:0;color:#4b5563;font-size:11px;text-align:center;">© BroadcastBeat · Digital Platform for Broadcast Engineering</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>`;
|
|
|
|
const res = await fetch("https://api.resend.com/emails", {
|
|
method: "POST",
|
|
headers: {
|
|
"Authorization": `Bearer ${RESEND_API_KEY}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
from: "onboarding@resend.dev",
|
|
to: [email],
|
|
subject: `You've been invited to contribute to BroadcastBeat`,
|
|
html: htmlBody,
|
|
}),
|
|
});
|
|
|
|
const data = await res?.json();
|
|
|
|
if (!res?.ok) {
|
|
throw new Error(data?.message || "Failed to send email");
|
|
}
|
|
|
|
return new Response(JSON.stringify({ success: true, id: data.id }), {
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Access-Control-Allow-Origin": "*",
|
|
},
|
|
});
|
|
} catch (error) {
|
|
return new Response(JSON.stringify({ error: error.message }), {
|
|
status: 500,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Access-Control-Allow-Origin": "*",
|
|
},
|
|
});
|
|
}
|
|
});
|