Enviar correos electrónicos con Nodemailer

Para enviar correo electrónico con Nodemailer, crea un transporte SMTP con nodemailer.createTransport() y pasa el sobre y el cuerpo del mensaje a transporter.sendMail().

La biblioteca estándar de Node.js no incluye un cliente SMTP integrado. Nodemailer cubre ese hueco: gestiona la negociación TLS, el pool de conexiones, la codificación MIME y los archivos adjuntos del correo saliente.

¿Cómo instalas y configuras Nodemailer?

Instálalo desde npm:

npm install nodemailer

Un transporte guarda los datos de conexión SMTP. Lo apuntas a un host y un puerto, y luego pasas las credenciales en auth:

import nodemailer from "nodemailer";

const transporter = nodemailer.createTransport({
  host: "smtp.example.com",
  port: 587,
  secure: false, // true for port 465, false for 587 (STARTTLS)
  auth: {
    user: process.env.SMTP_USER,
    pass: process.env.SMTP_PASS,
  },
});

El puerto 587 con secure: false usa STARTTLS, que eleva la conexión a TLS después del handshake. El puerto 465 requiere secure: true. Guarda el usuario y la contraseña en variables de entorno, nunca en el código fuente.

¿Cómo envías un mensaje?

Llama a sendMail con el sobre y el contenido. Devuelve una promesa, así que envuélvelo en async/await con un try/catch para que un envío fallido no haga caer el proceso:

async function main() {
  try {
    const info = await transporter.sendMail({
      from: '"Your App" <you@yourdomain.com>',
      to: "recipient@example.org",
      subject: "Your receipt",
      text: "Thanks for your order. This is the plain-text version.",
      html: "<p>Thanks for your order.</p>",
    });
    console.log("Sent:", info.messageId);
  } catch (err) {
    console.error("Send failed:", err);
  }
}

main();

Envía siempre tanto text como html. Algunos clientes muestran la parte de texto plano, y un mensaje sin alternativa de texto tiende a puntuar peor en los filtros de spam.

¿Cómo añades archivos adjuntos?

Pasa un arreglo attachments. Cada entrada puede leer desde una ruta, un buffer o un stream:

await transporter.sendMail({
  from: "you@yourdomain.com",
  to: "recipient@example.org",
  subject: "Your invoice",
  text: "Invoice attached.",
  attachments: [
    {
      filename: "invoice.pdf",
      path: "./invoices/invoice-1042.pdf",
    },
    {
      filename: "note.txt",
      content: "Generated at runtime, no file needed.",
    },
  ],
});

¿Cómo pruebas sin enviar correo real?

Nodemailer incluye Ethereal, un servicio SMTP falso que captura los mensajes en lugar de entregarlos. Obtienes una URL de vista previa por cada envío, ideal para desarrollo local:

const testAccount = await nodemailer.createTestAccount();

const transporter = nodemailer.createTransport({
  host: "smtp.ethereal.email",
  port: 587,
  secure: false,
  auth: {
    user: testAccount.user,
    pass: testAccount.pass,
  },
});

const info = await transporter.sendMail({
  from: "you@yourdomain.com",
  to: "test@example.org",
  subject: "Preview only",
  text: "This never leaves Ethereal.",
});

console.log("Preview:", nodemailer.getTestMessageUrl(info));

Ethereal sirve para inspeccionar lo que construiste. No te dice nada sobre si una bandeja de entrada real aceptaría el mensaje.

Envíalo con Bird

SMTP funciona, pero usarlo en producción implica operar un servidor de correo (o alquilar uno), calentar IPs y vigilar la reputación tú mismo. Una HTTP API se encarga de todo eso. No hay un socket SMTP que mantener abierto, y el proveedor gestiona la infraestructura de entregabilidad. Con la Bird de correo electrónico API el mismo envío es una sola llamada:

import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

const { data, error } = await bird.email
  .send({
    from: "onboarding@messagebird.dev",
    to: ["delivered@messagebird.dev"],
    subject: "Hello from Node",
    html: "<p>It works.</p>",
  })
  .safe();

El remitente onboarding@messagebird.dev y la dirección sandbox delivered@messagebird.dev confirman la integración antes de apuntar a un destinatario real. Los entornos serverless, como las funciones de Vercel y otros entornos de servidor JavaScript, usan esta vía HTTPS cuando no pueden mantener abiertas conexiones SMTP.

Preguntas frecuentes

¿Funciona Nodemailer en el navegador?

No. Nodemailer es una biblioteca del lado del servidor y depende de los módulos de red de Node. Los navegadores no pueden abrir conexiones SMTP, y poner credenciales en código del cliente las expondría. Envía desde un backend en su lugar.

¿Por qué enviar tanto texto como HTML?

Un mensaje multipart permite que cada cliente elija la parte que puede renderizar, y la alternativa en texto plano mejora cómo los filtros de spam interpretan el mensaje. Omitir text es una razón común por la que los correos terminan en spam.

¿Debería usar SMTP o una HTTP API?

SMTP está bien para volúmenes bajos y herramientas internas. Para envíos en producción a escala, una HTTP API elimina el servidor que de otro modo tendrías que operar e incorpora el manejo de entregabilidad. Muchos equipos usan Nodemailer en desarrollo y una API en producción.

Nodemailer es una opción sólida para hablar SMTP desde Node. Cuando prefieras no operar el servidor de correo detrás de él, lee la guía de envío de correo para ver la alternativa API de principio a fin.

Construye sobre la misma red.

Obtén una clave API de prueba de inmediato. El acceso a producción se desbloquea cuando añades un método de pago y verificas un remitente.

Start building with Bird in minutes.