En este post vamos a ver cómo enviar emails responsive con NodeJS utilizando Express, Sendgrid e Ink.

Finalmente, veremos cómo crear nuestras propias plantillas responsive con Yeoman de tal forma que sean fácilmente mantenibles y configurables.

El código de la aplicación de ejemplo que vamos a seguir lo puedes encontrar en este repositorio de Github.

¿Qué es Sendgrid?

Sendgrid es un servicio de envío de emails que proporciona un sistema eficaz de entrega de correos por lo que nos aseguramos que no acabarán en la bandeja de spam de nuestros destinatarios.

En su versión gratuita nos permite enviar hasta 400 emails diarios y 12.000 mensuales. Además posee un montón de estadísticas, informes de spam, filtros de cuentas inexistentes, etc... que lo convierten en una herramienta muy potente.

El código de ejemplo que vamos a ver está basado en este servicio por lo que lo primero que debes hacer es crearte una cuenta en Sendgrid.

Nota: es probable que tarden unas horas en activarte la cuenta para poder enviar emails.

Una vez tengamos la cuenta activa, debemos acceder a la sección Account Details > API Keys y crearnos una clave para poder utilizar la API del servicio. Apúntala porque la utilizaremos más adelante.


¿Qué es Ink?

Otro servicio que vamos a utilizar es Ink, que ofrece plantillas responsive que se ven bien en cualquier cliente de correo.

Como sabrás, para que una plantilla se visualice bien en todos los clientes de correo debemos maquetar con tablas. Además, todos los estilos deben estar colocados en cada una de las etiquetas html (estilos inline).


¿Qué necesitamos tener instalado?

Debemos tener instalado como mínimo:

De forma opcional, podemos instalar TSD package manager

    $ > npm install tsd@next -g

Nota: puedes ver para qué utilizo TSD en el anexo de este post.

Una vez tengamos esto instalado, seguimos estos pasos para descargar y configurar el ejemplo que vamos a seguir.


Show me the code...

Si has llegado hasta aquí, dispones de un ejemplo sobre cómo enviar emails responsive con NodeJS y Sengrid.

El ejemplo es algo básico pero puede ser un buen punto de partida para nuestros desarrollos. Vamos a echar un vistazo al código.

Estructura de directorios

Tenemos la siguiente estructura de directorios:

responsive-emails-service/
    L app/
        L views/
            email.hjs
            index.hjs
            page.hjs
        app.js
        config.js
    L node_modules/
        ... 
    L typings/
        ... ficheros de definición de Typescript
    env.json
    package.json
    README.md
  • app: carpeta que contiene la aplicación de ejemplo.

    • app.js está la aplicación
    • en la carpeta views están las plantillas que vamos a utilizar en este ejemplo.
    • config.js: fichero que se encarga de cargar la configuración de la aplicación.
  • node_modules: módulos necesarios para ejecutar el ejemplo.

  • typings: librerías de definición de Typescript.

  • env.json: parámetros de configuración de cada entorno de ejecución.

  • package.json: definición de la aplicación, dependencias, etc...

  • README.md: fichero de ayuda

Vamos a centrarnos un poco en los ficheros realmente importantes.

La aplicación de envío de emails

El fichero app/app.js contiene todo lo necesario para ejecutar la aplicación.

Lo primero que hago es cargar los módulos que voy a necesitar. Estos son:

  • express: framework para NodeJS
  • hogan.js: gestor de plantillas que voy a utilizar
  • path: utilidades para la manipulación y transformación de las rutas de los ficheros.
  • fs: módulo para operaciones de lectura/escritura de ficheros.
  • sendgrid: módulo para interactuar con la API de Sendgrid.

, y el código es:

    /// <reference path="../typings/node/node.d.ts"/>
    /// <reference path="../typings/express/express.d.ts"/>


    //  MÓDULOS NECESARIOS
    // --------------------
      var app = require('express')();
    var path = require('path');
    var hogan = require('hogan.js');
    var fs = require('fs');

A continuación, obtengo la configuración de la aplicación. Esta configuración dependen de las variables de entorno con el que se arranque el servidor NodeJS.

Además, inicializo el módulo sendgrid para interactuar con su API. Para ello, necesitamos disponer de una API Key tal y como comentamos anteriormente.

// Configuración de la aplicación
var conf = require('./config').config();

// Sendgrid
var sendgrid  = require('sendgrid')(conf.email.key);

Una vez tenemos todo preparado, le decimos a la aplicación dónde está la plantilla HTML que vamos a utilizar para el envío de emails y el motor con el que tiene que compilarla, en este caso Hogan.js.

  //  SETTINGS
  // ----------
  // hogan js templates
  app.set('views', path.join(__dirname, 'views'));
  app.set('view engine', 'hjs');

Una vez hecho eso, leemos del sistema de archivos el fichero que contiene el HTML (imporante hacerlo en UTF-8) y compilamos la plantilla.

  // obtener la plantilla de email
  var template = fs.readFileSync('./app/views/email.hjs','utf-8');

  // compilar la plantilla email
  var compiledTemplate = hogan.compile(template);

Finalmente, sólo nos queda definir las rutas de la aplicación:

  • /: página de inicio del ejemplo donde únicamente tenemos un par de enlaces para ejecutar el mismo.

    // Home
    app.get("/", function(req, res) {  
      res.render('index');
    });
    
  • /send: ruta encargada de enviar el email al destinatario. Lo único que hacemos es definir los datos de envío, la plantilla que debe renderizar y que hemos compilado previamente. A esta plantilla le pasamos el nombre del destinatario como parámetro.

    // Enviar email
    app.get('/send', function(req, res) {
        // NOTA: pon aquí el email de destino 
        var  receiver = 'hola@mi_dominio.com';
        var opcionesMail = {
            to:       receiver,
            from:     conf.email.from,
            subject:  'Hola!',
            html:     compiledTemplate.render({firstName: 'Koldo'})
        };
        sendgrid.send(opcionesMail, function(err, json) {
            var titulo = 'Email enviado correctamente';
            var texto = 'El email se ha enviado a la siguiente dirección: ' + receiver;
            if (err) {
              titulo = 'Se ha producido un error';
              texto = err;
            }
            res.render('page', {titulo: titulo, texto: texto});
        });
    });
    
  • /preview: ruta que permite previsualizar el email a enviar. Lo que hace es renderizar la plantilla compilada anteriormente añadiendo el nombre que le pasamos como parámetro a la misma.

    // Preview
    app.get('/preview', function(req, res) {
        res.render('email', {firstName: 'Koldo'});
    });
    

Finalmente le indicamos a la aplicación el puerto por el que tiene que exponer el servicio.

  //  ARRANCAR EL SERVER
  // --------------------
  // Escuchar en el puerto configurado
  app.listen(conf.port);

  // Log para saber cuando se arranca el servidor
  console.log('App escuchando en el puerto: ' + conf.port);

Plantilla simple

Como primera aproximación, podemos tener en el fichero app/views/email.hjs una plantilla con el siguiente contenido:

<!doctype html>
<html lang="es">
    <head>
      <meta charset="utf-8">
      <title>Ejemplo Responsive mailing con NodeJS y Sendgrid</title>
      <meta name="description" content="Respnsive mailing">
      <meta name="author" content="Koldo Hernández">
    </head>
    <body>
        <p>Hola {{ firstName }}</p>
    </body>
</html>

Como vemos, esta plantilla enviará un email básico con un simple saludo. Pero normalmente enviamos emails con más contenido y un aspecto mas currado. Para ello, vamos a utilizar plantillas html responsive.

Plantilla de email responsive

Para crear la plantilla base para el envío de nuestros emails, podemos obtener una de las plantillas de Ink que ofrece Ink.

A continuación, copiamos el código fuente de la misma y lo pasamos por el conversor. De esta forma, transformamos las clases css que tiene la plantilla aplicada en cada elemento html por estilos en línea.

Una vez hecho, copiamos el código fuente resultante en nuestra plantilla app/views/email.hjs. Tras reiniciar el servidor node, si accedemos a la http://localhost:8082/preview podremos ver la vista previa del email que vamos a enviar con la plantilla nueva.

Pero tenemos un problema, es que mantener estas plantillas y realizar modificaciones sobre ellas, no es muy cómodo. Para ello, vamos a utilizar el módulo Zurb Ink Generator.


Creando nuestras propias plantillas

Para poder crear y mantener nuestras propias plantillas de email responsive, vamos a crearnos otra aplicación de NodeJS. Esta nueva aplicación nos va a permitir crear y retocar las plantillas de nuestros emails antes de pasarlas a la aplicación que realizan los envíos.

Para ello, utilizaremos un interesante módulo llamado Zurb Ink Generator que nos facilita mucho la vida.

Instalar y configurar Zurb Ink Generator

Lo primero que tenemos que hacer es instalar el módulo Zurb Ink Generator. Lo haremos de forma global utilizando el comando:

$ > npm install -g generator-zurb-ink

A continuación nos creamos una nueva carpeta donde guardar la aplicación que nos permite crear las plantillas de email responsive:

$ > sudo mkdir <root_apps>/ink-templates

$ > cd <root_apps>/ink-templates

Una vez tenemos creada la carpeta y nos hemos posicionado en ella, ejecutamos el comando:

$ > yo

Lo que nos aparece es una asistente para configurar la tarea que queremos hacer. Seleccionamos (con las flechas) zurb ink y escogemos la plantilla de la que queremos partir: Sidebar hero.

Una vez acaba el proceso, tenemos en el fichero <root_apps>/ink-templates/index.html la plantilla de Ink con un formato amigable.

Modificar el template

Para probar la plantilla, tendremos que ejecutar (dentro de la carpeta <root_apps>/ink-templates/, por supuesto):

$ > gulp 

, y podremos ir realizando las modifiaciones que queramos y viendo los cambios al vuelo (live reload):

  • Añadir en el index.html las variables que posteriormente Hogan.js va a sustituir. En nuestro ejemplo, el nombre (firstName).

  • Modificar los estilos que nos proporciona Ink para adaptarlos a los nuestros (fichero bower_components/ink/css/ink.css o styles/styles.css).

Compilar el template

Una vez tengamos lista nuestra plantilla, únicamente tenemos que ejecutar:

$ > gulp build

, y en la carpeta build tendremos el archivo index.html con todos los estilos añadidos en línea, es decir, en las mismas etiquetas html.

Ya sólo nos queda copiar el código fuente de esta plantilla y pegarlo en el archivo app/views/emails.hjs de nuestra aplicación NodeJS que se encarga de realizar los envíos.


Anexo: ¿Qué es TSD?

TSD un paquete que nos permite buscar e instalar ficheros de definición de Typescript. Typescript es un lenguaje de programación creado por Microsoft y liberado como proyecto open source.

Tal y como lo define la Wikipedia:

Es un superconjunto de JavaScript, que esencialmente añade tipado estático y objetos basados en clases.

Con él, podemos beneficiarnos de las ventajas de los lenguajes orientados a objetos.

Un aspecto interesante es que podemos integrarlo en nuestro IDE (Sublime Text, Atom, Visual Studio Code, etc...) para obtener ayuda contextual y autocompletado de las clases de nuestros proyectos.

En mi caso, para no tener que entender la sintaxis de Typescript y únicamente beneficiarnos del tipado de datos y la integración con Visual Studio Code en los proyectos desarrollados con NodeJS, voy a instalar el paquete TSD package manage

Para instalarlo de forma global al sistema, ejecutamos el siguiente comando:

$ > npm install tsd@next -g

A continuación, vamos a la carpeta raíz del proyecto y ejecutamos:

$ > tsd install node

Esto creará automáticamente la carpeta typings dentro de nuestro proyecto y dentro de ella encontraremos el fichero node/node.d.ts que es el que nos ofrecerá la definición de las clases de NodeJS.

Si necesitásemos ayuda contextual de algún otro módulo de terceros, como Express.js, sólo tendríamos que ejecutar:

$ > tsd install express

Una vez nos hemos descargado los ficheros tsd en la carpeta typings, debemos incluir un comentario especial al principio de cada archivo js para que Visual Studio Code pueda obtener la ayuda contextual de cada clase.

/// <reference path="typings/node/node.d.ts"/>
/// <reference path="typings/express/express.d.ts"/>

Por tanto, tsd es el gestor de paquetes de Typescript (equivalente al npm de NodeJS). Existen un montón de paquetes en http://definitelytyped.org/tsd/.