Cómo Enviar correo electrónico a través de API en JavaScript (Tutorial de Node.js)
Omite la información estándar de SMTP. Esta guía te muestra cómo enviar correos electrónicos en Node.js usando API de correo electrónico unificado de Unipile - con código de copiar y pegar para Gmail, Outlook y SMTP en menos de 10 líneas de JavaScript.
import { UnipileClient } from 'unipile-node-sdk';
const client = nuevo UnipileClientprocess.env.UNIPILE_DSN,
process.env.UNIPILE_TOKEN
);
await cliente.email.enviar({
account_id: 'TU_ID_DE_CUENTA',
para: [{ nombre_a_mostrar: 'Alicia',
identificador: 'alice@example.com' }],
asunto: 'Hola desde Node.js',
body: '¡Enviado vía Unipile!
'
});Ejemplo de Node.js de 5 líneas
Si ya sabes qué es un Enviar correo electrónico API es y solo quiero enviar código de API de correo electrónico de JavaScript que realmente funcione, aquí está. El tutorial completo sigue a continuación.
npm install unipile-node-sdkUNIPILE_DSN y UNIPILE_TOKEN a tu .env archivo.client.email.enviar()account_id, a, temay cuerpo. Hecho.import { UnipileClient } from 'unipile-node-sdk';
const client = nuevo UnipileClientprocess.env.UNIPILE_DSN,
process.env.UNIPILE_TOKEN
);
const resultado = esperará cliente.email.enviar({
account_id: 'acc_xxxxxxxxxxxxxxxx',
para: [{
nombre_a_mostrar: 'Alicia Martín',
identificador: 'alice@acme.com'
}],
asunto: 'Hola desde Node.js',
body: '¡Enviado a través de la API de Unipile!
'
});
consola.log(resultado); // { tracking_id: 'msg_...' }Requisitos previos y configuración
Antes de poder usar el flujo de trabajo de JavaScript de la API de envío de correo electrónico en producción, necesitas cuatro cosas: una versión compatible de Node.js, el SDK de Unipile, una clave de API y un punto final de DSN.
fetch y de primer nivel await. Se recomienda Node 20 LTS para producción. Comprueba tu versión con node -v.api4.unipile.com:13444. Ambos son necesarios para inicializar el cliente..mjs archivos o conjunto "tipo":"módulo" en paquete.json. Para CommonJS, dinámico import() funciona también - ejemplos que se muestran a continuación.npm install unipile-node-sdkyarn add unipile-node-sdkpnpm agregar unipile-node-sdk# Credenciales de Unipile (nunca incluyas este archivo en el repositorio)
UNIPILE_DSN=https://api4.unipile.com:13444
UNIPILE_TOKEN=tu_token_de_acceso_aqui
# La ID de la cuenta de correo electrónico vinculada
ID_CUENTA_EMAIL=acc_xxxxxxxxxxxxxxxxAñadir .env a tu .gitignore. Usa dotenv o para el Node nativo 20.6+ --archivo-env bandera para cargarlo node --env-file=.env send.mjs.
Conectando tu primera cuenta de correo electrónico
En API de correo electrónico unificada usa un solo account_id para abstraer las diferencias de los proveedores. Vincula una cuenta una vez y luego llama client.email.enviar() idénticamente en los tres proveedores.
Selecciona tu proveedor a continuación para ver el fragmento de código exacto de Node.js. El account_id devuelto es lo que almacenas y reutilizas para cada envío posterior.
import { UnipileClient } from 'unipile-node-sdk';
const client = nuevo UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// Paso 1: generar un enlace de OAuth alojado para Gmail
const { url } = esperará cuenta.cliente.crearEnlaceAutenticacionHospedado({
tipo: 'GOOGLE',
success_redirect_url: process.env.OAUTH_CALLBACK_URL,
failure_redirect_url: process.env.OAUTH_CALLBACK_URL + '?error=1',
});
// Paso 2: redirige a tu usuario a `url`
consola.log('Redirigir al usuario a:', url);
// Paso 3: Unipile envía la account_id a tu callback
// Almacenarlo: process.env.EMAIL_ACCOUNT_ID = result.account_idimport { UnipileClient } from 'unipile-node-sdk';
const client = nuevo UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// Funciona para Outlook personal Y Microsoft 365 / Exchange Online
const { url } = esperará cuenta.cliente.crearEnlaceAutenticacionHospedado({
tipo: 'MICROSOFT',
success_redirect_url: process.env.OAUTH_CALLBACK_URL,
failure_redirect_url: process.env.OAUTH_CALLBACK_URL + '?error=1',
});
// Redirigir al usuario -> completa el flujo de OAuth de Microsoft
consola.log('Redirigir al usuario a:', url);
// Ver: /sincronización-de-correos-electrónicos-con-la-api-de-microsoft-graph-una-guía-para-desarrolladores/import { UnipileClient } from 'unipile-node-sdk';
const client = nuevo UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
// SMTP/IMAP: pasar credenciales directamente (sin redirección OAuth)
const account = esperará cuenta.cliente.create({
tipo: 'IMAP',
imap: {
usuario: process.env.IMAP_USUARIO,
contraseña: process.env.IMAP_PASS,
anfitrión: process.env.IMAP_HOST,
puerto: 993,
},
smtp: {
username: process.env.IMAP_USUARIO,
contraseña: process.env.IMAP_PASS,
anfitrión: process.env.SMTP_HOST,
puerto: 587,
},
});
consola.log(account.account_id); // guardar estoEnviar tu primer correo electrónico desde Node.js
Tres patrones listos para producción para el flujo de trabajo de JavaScript de la API de envío de correo electrónico: texto sin formato, HTML con CC/CCO y lectura del objeto de respuesta. Todos usan el mismo client.email.enviar() llamar.
import { UnipileClient } from 'unipile-node-sdk';
const client = nuevo UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
const resultado = esperará cliente.email.enviar({
account_id: process.env.ID_CUENTA_EMAIL,
para: [{ nombre_a_mostrar: 'Bob', identificador: 'bob@example.com' }],
asunto: 'Bienvenido/a a la plataforma',
body: 'Hola Bob, tu cuenta está lista.',
});
consola.log(result.tracking_id); // msg_xxxxxxxxxxxxxxxxconst resultado = esperará cliente.email.enviar({
account_id: process.env.ID_CUENTA_EMAIL,
para: [{ display_name: 'Alicia', identificador: 'alice@acme.com' }],
cc: [{ display_name: 'Gerente', identificador: 'boss@acme.com' }],
cc: [{ display_name: 'Auditoría', identificador: 'audit@internal.io' }],
asunto: 'Su factura #1042',
// cuerpo del HTML - el proveedor lo renderiza de forma nativa
body: `
Factura #1042
Monto a pagar: $299
Pagar ahora
`,
});
consola.log('Enviado:', result.tracking_id);| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
account_id | cadena | Requerido | ID de la cuenta de correo electrónico vinculada para enviar desde |
a | Destinatario[] | Requerido | Matriz de {nombre_a_mostrar, identificador} objetos |
tema | cadena | Requerido | Asunto del correo electrónico |
cuerpo | cadena | Requerido | Texto plano o cadena HTML |
cc | Destinatario[] | Opcional | Destinatarios en copia carbón |
con copia oculta | Destinatario[] | Opcional | copia oculta para destinatarios |
from | Destinatario | Opcional | Anular nombre para mostrar del remitente |
responder | cadena | Opcional | ID del mensaje del proveedor al que responder (hilos) |
archivos adjuntos | Arreglo | Opcional | Matriz de [nombre de archivo, Búfer] tuplas |
cabeceras_personalizadas | objeto[] | Opcional | Matriz de encabezados X personalizados |
opciones de seguimiento | objeto | Opcional | {abre, enlaces, etiqueta} - habilitar seguimiento de apertura/clic |
Obtén tu clave de API, vincula una cuenta de Gmail u Outlook en minutos y ejecuta los ejemplos de Node.js de esta guía contra buzones de correo reales.
Enviar adjuntos en Node.js
En archivos adjuntos campo acepta una matriz de [nombre de archivo, Búfer] tuplas. Lee el archivo con Node's fs.readFileSync o transmítelo con fs.promises.readFile.
fs.promises.readFile(ruta) para obtener un Buffer, luego pasar ['nombre del archivo.pdf', buffer]. Funciona para PDF, DOCX, imágenes, cualquier binario.cid: esquema. Haga referencia al mismo nombre de archivo utilizado en la tupla attachments: <img src="cid:logo.png">.pdfkit), recógelo en un Buffer y adjúntalo sin escribir en disco. Seguro para producción en entornos serverless.import { UnipileClient } from 'unipile-node-sdk';
import promesas como El fin de semana from 'nodo:fs';
const client = nuevo UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
Lee el archivo en un Buffer
const BufferPDF = esperará fs.leerArchivo('./factura.pdf');
await cliente.email.enviarclave_cuenta: proceso.env.ID_CUENTA_EMAIL,
para: [{ display_name: 'Cliente', identificador: 'client@example.com' }],
asunto: 'Su factura está adjunta',
body: 'Por favor, encuentre su factura adjunta.
',
adjuntos: [
['factura.pdf', pdfBuffer], // [nombre de archivo, Buffer]
],
});const [logotipo, informe] = esperará Promise.allfs.leerArchivo('./logo.png'),
fs.leerArchivo('./report.xlsx'),
]);
await cliente.email.enviar({
account_id: process.env.ID_CUENTA_EMAIL,
para: [{ nombre_a_mostrar: 'Equipo', identificador: 'team@acme.com' }],
asunto: 'Informe del primer trimestre',
body:
Informe Q1
Consulte la hoja de cálculo adjunta para obtener más detalles.
`,
adjuntos: [
['logo.png', logo], // en línea a través de cid:logo.png en el cuerpo
['report.xlsx', informar], // adjunto regular
],
});Respuestas, Hilos y Seguimiento
Vaya más allá de los envíos básicos: respuestas de hilos, encabezados personalizados para idempotencia, seguimiento de apertura/clics a través de webhooks y enviar un correo electrónico en nombre de un usuario.
1
Respondiendo a un hilo
Pase el ID del mensaje del proveedor (devuelto en la respuesta de envío original o al listar correos electrónicos) como responder. Unipile inyecta lo correcto En respuesta a y Referencias encabezados para que las respuestas se enlacen correctamente en Gmail, Outlook y clientes IMAP.
await cliente.email.enviar({
account_id: process.env.ID_CUENTA_EMAIL,
para: [{ nombre_a_mostrar: 'Alicia', identificador: 'alice@acme.com' }],
asunto: 'Re: Tu pregunta',
body: '¡Gracias por contactarnos! Aquí tienes la respuesta...
',
// ID del mensaje del proveedor del correo electrónico original
responder_a: 'msg_xxxxxxxxxxxxxxxx',
});
2
Encabezados personalizados e idempotencia
Utilice cabeceras_personalizadas para añadir cualquiera X- encabezado. Un patrón común es X-Idempotency-Key para evitar envíos duplicados al reintentar después de un tiempo de espera de red.
import { uuid aleatorio } from 'nodo:criptografía';
await cliente.email.enviar({
account_id: process.env.ID_CUENTA_EMAIL,
para: [{ nombre_a_mostrar: 'Bob', identificador: 'bob@example.com' }],
asunto: 'Confirmación de pedido #9981',
body: 'Se confirma tu pedido.
',
cabeceras_personalizadas: [
{ nombre: 'X-Idempotency-Key', valor: UUID aleatorio},
{ nombre: 'X-Order-ID', valor: '9981' },
],
});
3
Seguimiento de aperturas y clics a través de webhooks
Habilitar seguimiento en opciones de seguimiento. Unipile dispara un evento webhookemail.abierto / email.enlace_hace_clica tu URL de webhook registrada con el etiqueta Aquí te configuras para poder correlacionar eventos a tus IDs internos.
await cliente.email.enviar({
account_id: process.env.ID_CUENTA_EMAIL,
para: [{ nombre_a_mostrar: 'Plomo', identificador: 'lead@prospect.com' }],
asunto: 'Seguimiento de tu prueba',
body: 'Hola, quería saludar...
',
opciones_seguimiento: {
aperturas: true, // dispara el webhook email.opened
enlaces true, // dispara el webhook email.link_clicked
etiqueta: 'crm_lead_12345', // tu ID de correlación interna
},
});
4
Enviando en nombre de otro usuario
Al construir aplicaciones SaaS multi-inquilino, cada usuario final vincula su propia cuenta de correo electrónico. Almacene el account_id por usuario en tu base de datos y pásalo en el momento del envío. Consulta la guía completa en cómo enviar correos electrónicos en nombre de un usuario.
// Cada usuario tiene su propio account_id enlazado almacenado en tu base de datos
async function enviarComoUsuario(userId, a, asunto, cuerpo) {
const usuario = esperará base de datos.obtenerUsuario(userId);
return cliente.email.enviaraccount_id: user.unipile_account_id, // por-usuario
a, asunto, cuerpo,
});
}
El correo se envía desde el Gmail de Alice, no desde la dirección de tu servidor
await enviarComoUsuario('usuario_alice', destinatarios, asunto, cuerpo);¿Trabajando con Python en su lugar? Ver nuestro Implementación en Python guía.
Manejo de Errores y Reintentos
Los fallos de red y los límites de velocidad son inevitables a escala. Aquí tienes un patrón async/await de nivel de producción para tu implementación en JavaScript de la API de envío de correos electrónicos, con reintentos exponenciales y registro estructurado utilizando Winston o Pino.
seguimiento_id está poblado. No se necesita reintento.Reintentar después Encabezado. Usa retroceso exponencial.UNIPILE_TOKEN variable de entorno. No reintentar - arreglar credenciales.account_id no existe o fue revocado. Vuelve a vincular la cuenta.import { UnipileClient } from 'unipile-node-sdk';
import logger from './logger.mjs'; // Winston or Pino instance
const client = new UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
async function sendWithRetry(payload, maxAttempts = 4) {
let attempt = 0;
while (attempt < maxAttempts) {
try {
const result = await client.email.send(payload);
logger.info({ tracking_id: result.tracking_id }, 'Email sent');
return result;
} catch (err) {
const status = err?.status ?? err?.statusCode;
// Do not retry on client errors (4xx except 429)
if (status >= 400 && status !== 429 && status < 500) {
logger.error({ status, err }, 'Non-retryable error');
throw err;
}
attempt++;
if (attempt >= maxAttempts) throw err;
// Exponential backoff: 1s, 2s, 4s, 8s...
const delay = 1000 * 2 ** (attempt - 1);
logger.warn({ attempt, delay, status }, 'Retrying...');
await new Promise(r => setTimeout(r, delay));
}
}
}
// Usage
await sendWithRetry({
account_id: process.env.EMAIL_ACCOUNT_ID,
to: [{ display_name: 'User', identifier: 'user@example.com' }],
subject: 'Your report is ready',
body: 'Click to download.
',
});Mejores prácticas de seguridad en Node.js
Tu UNIPILE_TOKEN otorga acceso completo a la API. Nunca la expongas del lado del cliente. Ver el completo Guía de seguridad de API de correo electrónico para temas avanzados que incluyen DKIM, SPF y rotación de tokens OAuth.
UNIPILE_TOKEN debe permanecer en el servidor. Cualquier JavaScript del lado del navegador, incluidos los componentes de cliente de Next.js, el frontend de React o Vite, NO debe importar el token directamente./api/enviar-correo). En Express, un endpoint POST. Autentica a tus propios usuarios primero, luego llama al servidor de Unipile con el token de la variable de entorno.account_id sigue siendo válido. No necesitas manejar la expiración del token de acceso tú mismo.// client.js - NUNCA hagas esto
const cliente = new UnipileClient(
'https://api4.unipile.com:13444',
'sk_live_xxxxxxxxxx' ¡Expuesto!
);
// app/api/send-email/route.js
exportar asíncrono función POST(req) {
// verificar autenticación primero
const session = await getServerSession();
if (!session) return new Response(null,{status:401});
const client = new UnipileClient(
process.env.UNIPILE_DSN, // solo-servidor
process.env.UNIPILE_TOKEN // solo-servidor
);
await client.email.send({...});
}
Errores comunes (específicos de Node.js)
Estos son los errores más frecuentes que cometen los desarrolladores al integrar una API de envío de correos electrónicos en JavaScript por primera vez. Cada uno es fácil de evitar una vez que conoces el patrón, y todos se aplican por igual al contexto de la API de envío de correos electrónicos de Node.js.
await solo funciona en módulos ES (.mjs o "tipo":"módulo"). En CommonJS, envuelve tu llamada send en un asíncrono IIFE o usar .entonces(). El SDK funciona en ambos, solo elige el formato de módulo correcto.// CommonJS: envolver en IIFE asíncrona
(asíncrono () => {
const { UnipileClient } = esperará import('unipile-node-sdk');
const client = nuevo UnipileClient(process.env.UNIPILE_DSN, process.env.UNIPILE_TOKEN);
await cliente.email.enviar({ /* ... */ });
})();Promise.all se enviarán simultáneamente, lo que alcanzará los límites de tasa y provocará errores 429. Usa un limitador de concurrencia como límite-p para limitar las solicitudes paralelas.import límite de p from 'límite-p';
const límite = LímiteP(5); // máx 5 envíos simultáneos
const resultados = esperará Promise.alldestinatarios.mapar => límite(() => cliente.email.enviarid_de_cuenta: process.env.ID_CUENTA_EMAIL,
para: [r], asunto, cuerpo,
})))
);Tampón objeto - no es una cadena base64, no es una cadena UTF-8. Si tienes contenido base64 (por ejemplo, de un webhook o una respuesta de API), conviértelo primero: Buffer.from(cadenaBase64, 'base64').// INCORRECTO: pasando una cadena
adjuntos: [['archivo.pdf', 'JVBERi0xLjQ...']] // cadena base64 - ¡se rompe!
// CORRECTO: Objeto buffer
adjuntos: [['archivo.pdf', Tampón.from(cadena_base64, base64)]]
// o desde el disco:
adjuntos: [['archivo.pdf', await fs.leerArchivo('./archivo.pdf')]]enviar() La llamada bloqueará el proceso en Node 15+. Siempre await el resultado o adjuntar un .atrapó() manejador.// INCORRECTO: "dispara y olvida" - falla en caso de error en Node 15+
cliente.email.enviar(carga útil); // sin await, sin .catch()
// CORRECTO: siempre maneja la promesa
await cliente.email.enviar(carga útil) // opción 1: await
.captura(error => registrador.error(err)); // opción 2: .catch()UNIPILE_TOKEN son solo para Node.js del lado del servidor. La recuperación del navegador directamente a la API expondría su token. Utilice una ruta de backend (ruta API de Next.js, punto final de Express, función de Netlify/Vercel) como proxy.account_id de una cuenta de Gmail, Outlook o IMAP previamente vinculada. La API devuelve 404 si falta el `account_id` o si la cuenta fue desvinculada.Preguntas frecuentes
Preguntas frecuentes sobre el envío de correos electrónicos en JavaScript y Node.js con la API unificada de correo electrónico de Unipile.
unipile-node-sdk, inicializar UnipileClient Con tu DSN y token, vincule una cuenta de Gmail o Outlook a través de OAuth, luego llame client.email.enviar(). No hay servidor SMTP, ni puerto 587, ni configuración TLS necesaria de tu parte: Unipile se encarga de la capa de transporte.No, y no deberías. Llamar a la API de Unipile desde JavaScript en el navegador expondría tu UNIPILE_TOKEN a cualquier usuario que abra las DevTools. Siempre llame a la API desde un contexto Node.js del lado del servidor: una ruta de Express, una ruta de API de Next.js (app/api/), una Vercel Edge Function o una Netlify Function.
Tu frontend envía una solicitud a tu propio endpoint de backend, que autentica la sesión del usuario y luego llama a Unipile del lado del servidor.
Nodemailer se conecta directamente a un servidor SMTP desde tu proceso de Node.js. Requiere que gestiones las credenciales SMTP, manejes TLS, configures DKIM tú mismo y lidies con las peculiaridades de cada proveedor por separado.
La API de correo electrónico de Unipile es una capa de abstracción en la nube: vinculas cuentas a través de OAuth (no se necesitan credenciales SMTP para Gmail/Outlook), obtienes un SDK unificado para todos los proveedores, y Unipile maneja la transmisión, los reintentos y la actualización de tokens. La contrapartida es que tus envíos pasan por la infraestructura de Unipile en lugar de una conexión SMTP directa.
Sí. El unipile-node-sdk paquete se distribuye con definiciones de tipos de TypeScript. Obtienes autocompletado completo y seguridad de tipos para enviar() carga útil, incluyendo Destinatario, opciones de seguimiento, y el tipo de respuesta.
import { UnipileClient } from 'unipile-node-sdk';
// Tipos TS completos: el autocompletado funciona en VSCode
const cliente: UnipileClient = nuevo UnipileClient(dsn, token);
const resultado = esperará cliente.email.enviar({ /* ¡escrito! */ });Para envíos de gran volumen, usa un limitador de concurrencia (por ejemplo,. límite-p con 5-10 llamadas concurrentes), añadiendo reintento exponencial en respuestas 429 y distribuyendo los envíos entre varias cuentas enlazadas si es posible. Cada cuenta de correo electrónico enlazada tiene sus propios límites de envío establecidos por el proveedor (Gmail: ~500/día para cuentas normales, más alto para Workspace).
Para correo masivo/de marketing real a escala (millones de destinatarios), considere un ESP dedicado (Mailgun, SendGrid) junto con Unipile para envíos transaccionales y basados en OAuth.
Next.js: usar rutas de APIapp/api/enviar-correo/ruta.js) o Acciones de Servidor. Mantén la instanciación del SDK solo en el lado del servidor.
Nuxt: usar rutas de servidorservidor/api/enviar-email.post.tsEl SDK solo es compatible con Node.js, por lo que no puede incluirse en un componente reutilizable (composable) o un plugin que se ejecute en el cliente.
NestJS: crear un Módulo de correo electrónico con un servicio que envuelve UnipileClient. Inyéctalo donde necesites para activar envíos: en controladores, trabajos CRON o manejadores de eventos.
¿Aún tiene preguntas? Nuestro equipo está aquí para ayudarle.