68 lines
3.1 KiB
TypeScript
68 lines
3.1 KiB
TypeScript
import { corsHeaders } from "./cors.ts";
|
|
|
|
const respond = (body: unknown, status = 200) => new Response(JSON.stringify(body), {
|
|
status,
|
|
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
|
});
|
|
|
|
const escapeHtml = (value: string) => value.replace(/[&<>"']/g, (character) => ({
|
|
"&": "&", "<": "<", ">": ">", '"': """, "'": "'",
|
|
}[character] || character));
|
|
|
|
Deno.serve(async (req) => {
|
|
if (req.method === "OPTIONS") {
|
|
return new Response("ok", { headers: corsHeaders });
|
|
}
|
|
if (req.method !== "POST") {
|
|
return respond({ success: false, error: "Método no permitido." }, 405);
|
|
}
|
|
|
|
try {
|
|
const payload = await req.json();
|
|
const record = payload?.record || payload;
|
|
if (!record || typeof record !== "object") {
|
|
return respond({ success: false, error: "Datos de contacto no válidos." }, 400);
|
|
}
|
|
|
|
const fields = ["name", "email", "phone", "subject", "message"];
|
|
if (fields.some((field) => record[field] != null && typeof record[field] !== "string")) {
|
|
return respond({ success: false, error: "Datos de contacto no válidos." }, 400);
|
|
}
|
|
const name = (record.name || "").trim();
|
|
const email = (record.email || "").trim();
|
|
const phone = (record.phone || "").trim();
|
|
const subject = (record.subject || "").trim();
|
|
const message = (record.message || "").trim();
|
|
if (!name || name.length > 200 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) || email.length > 320 || phone.length > 100 || subject.length > 300 || message.length < 10 || message.length > 10000) {
|
|
return respond({ success: false, error: "Revisa los datos de contacto." }, 400);
|
|
}
|
|
|
|
// Configura estos secretos solo en Supabase, nunca en Coolify ni en VITE_*.
|
|
const apiKey = Deno.env.get("RESEND_API_KEY");
|
|
const sender = Deno.env.get("RESEND_FROM_EMAIL");
|
|
if (!apiKey || !sender) {
|
|
// Estado explícito, no una simulación de entrega: el formulario ya está guardado.
|
|
return respond({ success: false, status: "not_configured", message: "La notificación por correo no está configurada." });
|
|
}
|
|
|
|
const response = await fetch("https://api.resend.com/emails", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
body: JSON.stringify({
|
|
from: sender,
|
|
to: ["info@infinitustx.com"],
|
|
subject: `Nuevo mensaje de contacto: ${name.replace(/[\r\n]/g, " ")}`,
|
|
html: `<h2>Nuevo mensaje de contacto</h2><p><strong>Nombre:</strong> ${escapeHtml(name)}</p><p><strong>Correo:</strong> ${escapeHtml(email)}</p><p><strong>Teléfono:</strong> ${escapeHtml(phone)}</p><p><strong>Asunto:</strong> ${escapeHtml(subject)}</p><p>${escapeHtml(message).replace(/\n/g, "<br/>")}</p>`,
|
|
reply_to: email,
|
|
}),
|
|
});
|
|
if (!response.ok) {
|
|
console.error("El proveedor de correo rechazó la solicitud:", response.status);
|
|
return respond({ success: false, error: "No se pudo enviar la notificación por correo." }, 502);
|
|
}
|
|
return respond({ success: true });
|
|
} catch {
|
|
return respond({ success: false, error: "No se pudo procesar la notificación." }, 400);
|
|
}
|
|
});
|