Replace Resend with n8n webhook relay for emails
- email.ts: POST to N8N_EMAIL_WEBHOOK_URL instead of Resend API - env.ts: replace RESEND_API_KEY with N8N_EMAIL_WEBHOOK_URL - .env.example: document new env var - Add n8n workflow JSON (Webhook -> Gmail -> Respond) ready to import
This commit is contained in:
@@ -22,8 +22,8 @@ export const env = {
|
||||
SUPABASE_URL: required('SUPABASE_URL'),
|
||||
SUPABASE_SERVICE_ROLE_KEY: required('SUPABASE_SERVICE_ROLE_KEY'),
|
||||
|
||||
// Email — Resend
|
||||
RESEND_API_KEY: required('RESEND_API_KEY'),
|
||||
// Email — n8n webhook (relé a Gmail)
|
||||
N8N_EMAIL_WEBHOOK_URL: required('N8N_EMAIL_WEBHOOK_URL'),
|
||||
EMAIL_FROM: optional('EMAIL_FROM', 'Naturcalabacera <reservas@naturcalabacera.com>'),
|
||||
|
||||
// Destinatarios de notificaciones (configurables, sin hardcodear)
|
||||
|
||||
@@ -7,40 +7,34 @@ interface SendEmailOptions {
|
||||
replyTo?: string;
|
||||
}
|
||||
|
||||
interface ResendResponse {
|
||||
id?: string;
|
||||
error?: { message: string; name: string };
|
||||
}
|
||||
|
||||
/**
|
||||
* Envía un email usando la API de Resend.
|
||||
* Docs: https://resend.com/docs/api-reference/emails/send-email
|
||||
* Envía un email a través del webhook de n8n.
|
||||
* El workflow de n8n recibe { to, subject, html } y lo envía vía Gmail.
|
||||
*/
|
||||
export async function sendEmail(options: SendEmailOptions): Promise<{ success: boolean; id?: string; error?: string }> {
|
||||
try {
|
||||
const res = await fetch('https://api.resend.com/emails', {
|
||||
const to = Array.isArray(options.to) ? options.to.join(', ') : options.to;
|
||||
|
||||
const res = await fetch(env.N8N_EMAIL_WEBHOOK_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.RESEND_API_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
from: env.EMAIL_FROM,
|
||||
to: Array.isArray(options.to) ? options.to : [options.to],
|
||||
to,
|
||||
subject: options.subject,
|
||||
html: options.html,
|
||||
...(options.replyTo && { reply_to: options.replyTo }),
|
||||
from: env.EMAIL_FROM,
|
||||
replyTo: options.replyTo,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json() as ResendResponse;
|
||||
|
||||
if (!res.ok || data.error) {
|
||||
const errorMsg = data.error?.message ?? `HTTP ${res.status}`;
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => '');
|
||||
const errorMsg = `HTTP ${res.status}${text ? ` — ${text.slice(0, 200)}` : ''}`;
|
||||
console.error('[email] Error al enviar:', errorMsg);
|
||||
return { success: false, error: errorMsg };
|
||||
}
|
||||
|
||||
const data = await res.json().catch(() => ({})) as { id?: string };
|
||||
return { success: true, id: data.id };
|
||||
} catch (err) {
|
||||
const errorMsg = err instanceof Error ? err.message : 'Error desconocido';
|
||||
|
||||
Reference in New Issue
Block a user