Como enviar emails con Mailgun en Nodejs

nodeJS abr. 30, 2020

Quieras o no, enviar correos electrónicos es una característica muy solicitada en cualquier proyecto de desarrollo web y móvil nieguenmelo!, esto significa que debes tener disponible alternativas que se acomoden a lo que tu proyecto o el de tu cliente necesite, ahora, los usos más comunes son para enviar correos de bienvenida, boletines informativos, correos de recuperación de contraseñas, activaciones de cuentas, etc, por eso el objetivo de este post es aprender como enviar correos utilizando Mailgun, acompañame..

¿Por qué Mailgun?

Yo me preguntaría ¿Y por que no?, Mailgun en pocas palabras es una alternativa muy potente, puedes rastrear las entregas de los correos y ver cuales emails se enviaron satisfactoriamente y cuales no, su API está muy bien diseñada para soportar el envío de cargas de millones de emails, lo que sí considera hay un número límite de emails que puedes enviar al mes, actualmente 5k, para iniciar esta muy bien, pero si ya tienes una buena cantidad de usuarios te recomiendo iniciar con la versión de pago.

Requisitos previos y que asumo que los tienes

  • Tienes cuenta en Mailgun
  • Tienes cuenta en Digital Ocean con domino asociado.

Registro de un dominio en Mailgun

Considerando que ya estás registrado(a) en Mailgun, iniciaremos el proceso registrando un dominio, entra al dashboard y dirígete a la sección de domains:

Opciones de mailgun

Y luego dale un click a agregar nuevo dominio.

Agregar dominio

Se mostrará un formulario similar al siguiente, aquí es donde empieza la configuración

Configuración de dominio

Solo debemos completar 3 datos, pasamos a explicar:

  1. Puedes agregar un nombre de dominio sin embargo mailgun recomienda usar un sub dominio, así que mejor le hacemos caso para evitar problemas y ponemos mg2.eldevsin.site.
  2. Escogemos la región, solo hay dos opciones US (Estados unidos) o EU (Europa) aquí depende de en donde te encuentres, mientras más cerca menos latencia.
  3. Qué tan larga es la clave generada para autorizar el envío de correos por un determinado dominio, 1024 es suficiente, aquí tienes un enlace si quieres saber más.

Le das un click al botón de agregar dominio para pasar al siguiente paso, encontrarás un formulario similar al siguiente:

Registros TXT
Registros MX
Registro CNAME

Esos valores son los que debes ingresar en tus registros DNS para permitir que Mailgun pueda verificar tu dominio, solo son 5 registros: 2 de TXT, 2 de MX y 1 CNAME. Según el proveedor que utilices podrás configurar los registros DNS de acuerdo a su respectiva documentación, para este ejemplo como lo mencionamos anteriormente utilizaremos Digital Ocean, sigamos.

Registro de DNS en Digital Ocean

Estoy asumiendo que ya tienes una cuenta Digital Ocean, tu dominio asociado y funcionando, si no lo tienes ve corriendo y regresas a continuar.

Cuando estes en el dashboard de DO, dirígete a Networking, allí empezaremos la magia.

Selecciona Networking en DO

Aparecerá tu lista de dominios registrados, selecciona el dominio que vas a verificar.

Lista de dominios

Una vez dentro podrás registrar los DNS en cada pestaña, en este caso debes registrar los valores para TXT, MX y CNAME.

Agregando registros DNS

Te debe quedar algo similar a lo siguiente:

Resultado de agregar registros DNS

Nota que agregamos las claves y valor con el tipo de registro al que va asociado, ahora solo debes regresar a la sección de dominios de Mailgun y dale al botón de verificar:

Verificar Dominio

Luego de eso ya debes ver a tu subdominio o dominio con un icono verde que significa que ya esta verificado.

Dominios verificados

El proyecto en nodeJS

Para empezar como ya estamos acostumbrados por aquí ubícate en un directorio de tu preferencia y ejecutas npm init para iniciar el proyecto, y le das aceptar a todo lo que mueva, si ya tienes un proyecto en marcha puedes obviar este paso:

npm init
Iniciar package.json

Para este micro ejemplo vamos a utilizar dos dependencias:

  • mailgun-js: Libreria oficial de mailgun.
  • dotenv: Librería para leer variables de entornos.
Package.json generado y dependencias

Agrega las librerías manualmente en tu package.json, esto es una buena práctica porque evitamos que se instale una versión superior que en un futuro no sea compatible con nuestro proyecto y termine rompiéndolo. Ok, aclarado eso, ejecuta la instalación con:

// con npm
npm install

// o

// con yarn
yarn install
Instalar dependencias

API Keys para conectar con Mailgun

Para enviar emails a través de Mailgun es necesario utilizar una key que le permita saber quien quiere utilizar su API y que permisos tiene, así que primero regresamos al dashboard de Mailgun y vamos a la sección de configuración para ver las API Keys que tenemos disponibles:

Apartado de configuración y dentro API Keys

En el apartado de seguridad verás 3 claves, para este ejemplo vamos a utilizar la clave privada, para verla completamente dale click al icono de la vista.

API keys

La clave la agregaremos en el archivo .env a la variable llamada MAILGUN_APIKEY, de esta forma la identificaremos para usarla en el código que armaremos más adelante.

Archivo .env

Nota importante: Las claves de acceso siempre deben ir como variables de entorno, no cometas el error de subirlas al repositorio a menos que estén encriptadas (en otro post hablaremos de esto, síguenos xD), si es un repo privado y donde solo estas tu tal vez pueda ser que no pasa nada, pero evita hacer eso, no te imaginas cuantas empresas han caído en algo tan básico.

El código en node

Ahora crearemos un nuevo archivo index.js, donde agregaremos un poco de código, tal cual como el siguiente:

require('dotenv').config(); // 1

const mailgun = require('mailgun-js')({ // 2
  apiKey: process.env.MAILGUN_APIKEY,
  domain: 'mg2.eldevsin.site',
});
Importación de dependencias en index.js

En esta primera parte estamos importando dotenv (1) y a la vez ejecutamos la función config() para que disponga de las variables que tenemos en el archivo .env que creamos en la sección anterior.

Luego en la siguiente línea importamos el paquete mailgun-js, y lo instanciamos(2) pasándole un valor a la clave apiKey, que viene de la variable de entorno y que podemos acceder a través de process.env.

const mailgun = ...

const send = async (email, name) => {
  const payload = { // 1
    from: 'Prueba Email <notificaciones@eldevsin.site>',
    to: email,
    text: `${name}, esta es una prueba de envio de email usando mailgun + nodejs + digital ocean. Apuntate a las notificaciones de el dev sin site.`,
    // html: `<p>${name}, esta es una prueba de envio de email usando mailgun + nodejs + digital ocean. <strong>Apuntate a las notificaciones de el dev sin site.</strong></p>`,
    subject: 'La prueba de envio fue exitosa',
  };

  let success = true;
  try {
    success = await mailgun.messages().send(payload); // 2
  } catch (e) {
    success = false;
  }

  console.log(success);
};
Función send

Básicamente acabamos de crear una función que recibe dos parámetros email y name (nombre del destinatario), nos sirven para crear el payload(1), un objeto con configuración básica que necesita Mailgun para enviar el mensaje, algunas de las opciones son las siguientes:

  • from: Nombre y correo de quién envía el email, antes del @ puedes anteponer el nombre que quieras, por ejemplo ventas@.., no-reply@..., contacto@..., o lo que prefieras.
  • to: Email destinatario, aquí puedes agregar un correo(string), o un array de correos(array de strings).
  • text: Contenido del email con un texto común.
  • html: Contenido del cuerpo del email con html.
  • subject: Asunto del email, aquí también texto plano.

Finalmente podemos proceder a enviar el mensaje(2), de acuerdo a la clase Mailgun en typescript, dispone de una función messages(), que devuelve la interfaz de tipo Messages, y con ella disponemos de la función send(), que devuelve una promesa, ¿de donde me saque eso?.. del propio código de la librería:

Bien, solo queda ejecutar la función que previamente declaramos:

const send = async (email, name) => {...}
...
    
send('emaildedestinoaqui@gmail.com', 'Fernando Palacios');
Ejecución de función send

Ahora cruzamos los dedos y esperamos que llegue el mensaje en la bandeja de entrada...

By Giphy

Que no te engañe el gif anterior, solo algunos segundos después de enviar el mensaje, esto apareció en el correo...

Cuando enviamos el contenido en texto común:

Envio de email con texto

Este otro cuando enviamos el correo con el contenido en html:

Envío de email con html

Ignora las horas de llegada, este post fue construido en mis ratos libres.

Enviar un archivo adjunto (attachment)

Hasta este punto podemos enviar emails a través este servicio, sin embargo vamos a dar un paso más allá y esta vez enviaremos archivos adjuntos, sigamos.

Entonces lo que haremos será enviar una imagen que se encuentra en nuestro directorio como un adjunto.

Imagen a enviar

Regresamos a nuestro archivo el index.js.

const path = require('path');
const fs = require('fs');

const image = fs.readFileSync(path.join(__dirname, 'fox.png')); // 1
Cambios en index.js

Vamos a añadir un poco de código, nos apoyamos del módulo path para trabajar sobre el directorio y concatenar la ubicación actual de index.js (__dirname) junto al nombre de archivo fox.js, luego con el módulo fs usamos la función readFileSync() para leer el archivo que se encuentra en la ruta construida, con eso ya tenemos un Buffer de la imagen disponible para los siguientes pasos.

Ahora es necesario modificar un poco función send() que definimos.

const image = ...


const send = async (email, name) => {
  const attachment = new mailgun.Attachment({ // 1
    data: image,
    filename: 'fox.png',
  });

  const payload = {
    from: 'Prueba Email con archivo <notificaciones@eldevsin.site>',
    to: email,
    text: `${name}, esta es una prueba de envio de email usando mailgun + nodejs + digital ocean. Apuntate a las notificaciones de el dev sin site.`,
    subject: 'La prueba de envio fue exitosa - con archivo',
    attachment, // 2
  };
   
  ...
}
Cambios en función send()

Son solo dos pasos, el primero crear una instancia de la clase Attachment(1), esto se consigue rápidamente con la misma librería, para indicarle lo que se va a adjuntar, como mínimo, debes ingresar en la key data una url de ruta de archivo, un Buffer, o una instancia de Stream, y como su propio nombre lo dice en la key filename va el nombre de archivo.

Como segundo paso, el objeto attachment debes pasarlo al payload, específicamente a la clave attachment(2).

Ahora ejecuta nuevamente el archivo index.js y corre a tu bandeja, debes encontrar algo similar a:

Resultado de prueba enviando un archivo

Y con eso ya estas apto para lanzar correos directo a la bandeja de entrada de tus usuarios!

Lo obligatorio (espero que para ti también)

Déjame saber que te pareció este post en los comentarios, ¿te parece útil y sencilla la forma de enviar emails a través de Mailgun?, si consideras que este post te ha aportado un grandioso valor, compártelo con tus amigos, no dejes de seguirnos en nuestras redes sociales y apúntate a las notificaciones para ser el primero en enterarte de nuestro siguiente post...nos vemos en una próxima entrega.

By GIPHY

Fernando Palacios

¡Hoy es un gran día para hacer grandes cosas!

¡Genial! Te has suscrito con éxito.
¡Genial! Ahora, completa el checkout para tener acceso completo.
¡Bienvenido de nuevo! Has iniciado sesión con éxito.
Éxito! Su cuenta está totalmente activada, ahora tienes acceso a todo el contenido.