Cómo definir plantillas y enviar correos electrónicos con joystick

Cómo configurar un servicio SMTP, preparar una plantilla de correo electrónico con los componentes de Joystick y enviar un correo electrónico con la función email.send() en @joystick.js/node.

Primeros pasos

Para este tutorial, vamos a utilizar el marco JavaScript de pila completa de CheatCode, Joystick. Joystick reúne un marco de interfaz de usuario de front-end con un back-end de Node.js para crear aplicaciones.

Para comenzar, querremos instalar Joystick a través de NPM. Asegúrese de estar usando Node.js 16+ antes de instalar para garantizar la compatibilidad (lea este tutorial primero si necesita aprender a instalar Node.js o ejecutar varias versiones en su computadora):

Terminal

npm i -g @joystick.js/cli

Esto instalará Joystick globalmente en su computadora. Una vez instalado, vamos a crear un nuevo proyecto:

Terminal

joystick create app

Después de unos segundos, verá un mensaje desconectado de cd en su nuevo proyecto y ejecute joystick start :

Terminal

cd app && joystick start

Después de esto, su aplicación debería estar ejecutándose y estamos listos para comenzar.

Configuración de SMTP

Antes de centrarnos en el código, para realmente enviar nuestro correo electrónico, necesitaremos acceso a un proveedor de SMTP. Hay bastantes opciones por ahí. Si tiene un favorito, siéntase libre de usarlo, pero para este tutorial le recomendaremos Matasellos. Postmark es un excelente servicio SMTP que ofrece, en mi opinión, el mejor producto SMTP del mercado.

Si aún no tiene una cuenta, diríjase a su página de registro y cree una. Una vez que haya iniciado sesión, Postmark creará automáticamente un "servidor" (un servidor en Postmark es el proyecto relacionado con la aplicación para la que está enviando correo electrónico) llamado "Mi primer servidor".

Una vez que haya iniciado sesión, debería ver algo como esto:

Desde aquí, deberá hacer clic en la pestaña "Tokens API" justo a la derecha de la pestaña resaltada "Flujos de mensajes".

Si coloca el cursor sobre la entrada poblada junto a "Tokens de la API del servidor", se le dará la opción de hacer clic y copiar el valor en el cuadro. Adelante, haz esto y luego abre el /settings.development.json archivo en la raíz de la aplicación Joystick que creamos anteriormente.

/configuraciones.desarrollo.json

{
  "config": {
    "databases": [
      {
        "provider": "mongodb",
        "users": true,
        "options": {}
      }
    ],
    "i18n": {
      "defaultLanguage": "en-US"
    },
    "middleware": {},
    "email": {
      "from": "<Default Email To Send From>",
      "smtp": {
        "host": "smtp.postmarkapp.com",
        "port": 587,
        "username": "<Paste Your Server API Token Here>",
        "password": "<Paste Your Server API Token Here>"
      }
    }
  },
  "global": {},
  "public": {},
  "private": {}
}

En este archivo, bajo el config objeto, busque el email objeto. Aquí, para el username y password campos, queremos pegar el valor que acaba de copiar (como veremos, al enviar un correo electrónico, así es como Postmark autentica su cuenta y sabe enviar el correo electrónico desde su Matasellos de cuenta).

A continuación, para el host campo que queremos ingresar smtp.postmarkapp.com y para el port queremos ingresar el número 587 (este es el puerto de correo electrónico seguro). Finalmente, para el from desea ingresar la dirección de correo electrónico predeterminada desde la que enviará (por ejemplo, [email protected] ). Para este tutorial, es aconsejable usar la misma dirección de correo electrónico con la que creó su cuenta de Matasellos, ya que habilitarán solo esa dirección para enviar correo electrónico por defecto . Correo electrónico enviado from cualquier otra dirección será rechazada hasta que Postmark apruebe su cuenta (tienen un proceso de aprobación que es bastante rápido y ayuda a evitar que los spammers dañen la reputación del remitente para cuentas legítimas).

Una vez que esto esté configurado, de vuelta en el sitio de Matasellos, queremos dirigirnos a la página de Firmas del remitente para asegurarnos de que el correo electrónico que acaba de ingresar para from arriba está configurado.

Si está en la lista, simplemente verifique esa dirección de correo electrónico y haga clic en el enlace de verificación. Si la dirección que ingresó es no en la lista, diríjase a la página "Agregar una nueva firma" y agréguela para que el matasellos no bloquee sus mensajes.

Una vez hecho esto, y su dirección verificada, el envío debería funcionar como se esperaba. Si no funciona, Matasellos se lo indicará en la pestaña "Actividad" de su servidor.

Eso es todo lo que necesitamos hacer para la configuración. Ahora, pasemos a conectar nuestra plantilla de correo electrónico.

Creación de una plantilla de correo electrónico

Al igual que las páginas y otros componentes de Joystick, las plantillas de correo electrónico se crean utilizando componentes de Joystick. Esto significa que puede usar la misma API familiar que usa para crear la interfaz de usuario de su aplicación para escribir sus correos electrónicos (al final del día, todavía está escribiendo HTML y CSS para sus correos electrónicos, por lo que no hay una curva de aprendizaje).

En su proyecto, ahora, queremos crear una carpeta especial email en la raíz de su aplicación y luego en esa carpeta, agregue un archivo invoice.js :

/correo electrónico/factura.js

import ui from '@joystick.js/ui';

const Invoice = ui.component({
  render: () => {
    return `
      <div>
      </div>
    `;
  },
});

export default Invoice;

Para nuestro ejemplo, crearemos una plantilla de correo electrónico que represente una factura para un cliente, tomando una dirección y algunos elementos de línea como accesorios. Debido a que el contenido no es muy importante aquí, avancemos y completemos nuestra plantilla de esqueleto anterior con nuestro contenido y analicemos lo que está haciendo:

/correo electrónico/factura.js

import ui from '@joystick.js/ui';

const Invoice = ui.component({
  render: ({ props, each }) => {
    return `
      <div class="invoice">
        <h4>Invoice</h4>
        <address>
          ${props.name}<br />
          ${props.address}<br />
          ${props.suite}<br />
          ${props.city}, ${props.state} ${props.zipCode}
        </address>
        <table>
          <thead>
            <tr>
              <th class="text-left">Item</th>
              <th>Price</th>
              <th>Quantity</th>
              <th>Total</th>
            </tr>
          </thead>
          <tbody>
            ${each(props.items, (item) => {
              return `
                <tr>
                  <td>${item.description}</td>
                  <td class="text-center">$${item.price}</td>
                  <td class="text-center">x${item.quantity}</td>
                  <td class="text-center">$${item.price * item.quantity}</td>
                </tr>
              `;
            })}
          </tbody>
          <tfoot>
            <tr>
              <td colspan="2"></td>
              <td colspan="1" class="text-center"><strong>Total</strong></td>
              <td colspan="1" class="text-center">
                $${props.items.reduce((total, item) => {
                  total += (item.price * item.quantity);
                  return total; 
                }, 0)}
              </td>
            </tr>
          </tfoot>
        </table>
      </div>
    `;
  },
});

export default Invoice;

Actualizando nuestro render() función para incluir nuestro HTML completo aquí, tenemos tres componentes principales:

  1. Un <h4></h4> etiqueta que describe nuestra plantilla como una "Factura".
  2. Un <address></address> etiqueta que muestra la dirección de la persona a la que le enviamos la factura.
  3. A <table></table> para representar elementos de línea.

Para nuestro render() firma de función, hemos agregado un solo argumento que se está desestructurando (en JavaScript, esto significa "quitar" propiedades de un objeto, asignando esas propiedades a variables en el alcance actual del mismo nombre) para darnos dos variables:props y each .

El primero, props , contendrá los accesorios o propiedades que pasamos a nuestra plantilla cuando enviamos nuestro correo electrónico. El segundo, each es una función (conocida como función de representación en Joystick) que nos ayuda a recorrer una matriz y devolver algo de HTML para cada elemento de la matriz. Aquí, para cada una de nuestras líneas de pedido en props.items queremos generar una fila de la tabla que genere el contenido de ese elemento (y hacer algunas multiplicaciones en su price y quantity campos).

La única otra cosa para llamar la atención aquí está en el <tfoot></tfoot> parte de nuestra mesa. Aquí, estamos sumando todas las líneas de pedido utilizando un JavaScript simple Array.reduce() función para "reducir" la matriz de items en un solo valor, en este caso, un número entero que representa el total de todos los elementos en el props.items matriz.

Eso es todo para nuestro HTML. Ahora, muy rápido antes de continuar con el envío, agreguemos algo de CSS para mejorar un poco las cosas:

/correo electrónico/factura.js

import ui from '@joystick.js/ui';

const Invoice = ui.component({
  css: `
    .invoice {
      padding: 20px;
    }

    h4 {
      margin: 0;
      font-size: 20px;
    }

    address {
      margin: 20px 0;
    }

    .text-left {
      text-align: left;
    }

    .text-center {
      text-align: center;
    }

    table {
      width: 100%;
      border: 1px solid #eee;
    }

    table tr th,
    table tr td {
      border-bottom: 1px solid #eee;
      padding: 10px;
    }

    table tfoot tr td {
      border-bottom: none;
    }
  `,
  render: ({ props, each }) => {
    return `
      <div class="invoice">
        ...
      </div>
    `;
  },
});

export default Invoice;

No sucede mucho aquí:solo limpiamos el espacio y agregamos algunos bordes a nuestra tabla para que se vea más presentable y fácil de leer en nuestro correo electrónico.

Lo bueno de esto es que cuando enviamos nuestro correo electrónico, Joystick tomará automáticamente el CSS que acabamos de agregar y lo alineará en nuestro HTML (esto significa agregar style atributos a los elementos apropiados en nuestro HTML) para que sea más amigable para los clientes de correo electrónico HTML.

Con eso, a continuación, pasemos a probar y enviar nuestro correo electrónico.

Enviar un correo electrónico

Antes de conectar nuestro envío, muy rápido, echemos un vistazo a cómo podemos probar y obtener una vista previa de nuestro correo electrónico HTML. Debido a que nuestro correo electrónico es solo un componente de Joystick, al igual que cualquier otra página o componente de nuestra aplicación, podemos representarlo usando el res.render() función que nos da Joystick en nuestro router.

/index.servidor.js

import node from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/": (req, res) => {
      res.render("ui/pages/index/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/email/invoice": (req, res) => {
      res.render(`email/invoice.js`, {
        props: {
          name: 'Bert',
          address: '1234 Sesame St.',
          suite: '#123',
          city: 'Sesame',
          state: 'ST',
          zipCode: '12345',
          items: [
            { description: 'Basketball', price: 10.00, quantity: 2 },
            { description: 'Football', price: 7.00, quantity: 5 },
            { description: 'Baseball', price: 4.95, quantity: 20 }
          ],
        },
      });
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

En nuestro /index.server.js archivo creado para nosotros cuando ejecutamos joystick create app anteriormente, aquí, estamos agregando una ruta llamada /email/invoice y llamando al res.render('email/invoice.js') . Esto le dice a Joystick que queremos renderizar el componente en la ruta especificada. Además, como sabemos que nuestro componente esperará algunos accesorios, a través del objeto de opciones pasado como segundo argumento a res.render() estamos especificando un props valor que se pasa un objeto de props queremos transmitir a nuestro componente.

Aquí, estamos pasando todos los valores esperados para nuestra plantilla, específicamente, la dirección del destinatario y los artículos que ordenó. Ahora, si abrimos http://localhost:2600/email/invoice en un navegador, deberíamos ver nuestra plantilla representada en la pantalla:

Si bien esto no nos dará una perfecta Representación de cómo se verá nuestro correo electrónico en un cliente de correo electrónico (los clientes de correo electrónico son notoriamente difíciles e inconsistentes para renderizar/diseñar), es una excelente manera de depurar nuestra plantilla sin tener que enviar un montón de correos electrónicos.

Ahora que podemos verificar que nuestra plantilla está funcionando, a continuación, enviémosla. Para hacerlo, vamos a usar el email.send() método de @joystick.js/node :

/index.servidor.js

import node, { email } from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/": (req, res) => {
      res.render("ui/pages/index/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/email/send": (req, res) => {
      email.send({
        to: '[email protected]',
        from: '[email protected]',
        subject: 'Invoice',
        template: 'invoice',
        props: {
          name: 'Bert',
          address: '1234 Sesame St.',
          suite: '#123',
          city: 'Sesame',
          state: 'ST',
          zipCode: '12345',
          items: [
            { description: 'Basketball', price: 10.00, quantity: 2 },
            { description: 'Football', price: 7.00, quantity: 5 },
            { description: 'Baseball', price: 4.95, quantity: 20 }
          ],
        },
      });
      res.send('Sent');
    },
    "/email/invoice": (req, res) => {
      ...
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

Arriba, hemos importado el email objeto de @joystick.js/node y hacia abajo en nuestras rutas, hemos agregado una ruta adicional /email/send (esto hace que sea más fácil de enviar; en realidad, le gustaría llamar al email.send() en respuesta al comportamiento real del usuario en algo así como un punto final de establecimiento) y dentro, estamos llamando a email.send() . Esta función enviará nuestro correo electrónico utilizando la conexión SMTP que configuramos anteriormente (a través de Matasellos si nos sigue o cualquier proveedor que haya especificado).

Aquí, pasamos algunos valores diferentes:

  1. to cuál es la dirección de correo electrónico a la que queremos enviar nuestro correo electrónico de prueba.
  2. from cuál es el correo electrónico desde el que queremos enviar (si omite esto, Joystick usará el from especificó en su config.email.from campo en /settings.development.json ).
  3. subject cuál es la línea de asunto que el destinatario verá en su bandeja de entrada.
  4. template que es el nombre del archivo bajo el /email directorio que contiene la plantilla que queremos usar.
  5. props cuáles son los accesorios que queremos pasar a nuestra plantilla antes de renderizar/enviar.

¡Eso es todo! Para asegurarnos de que nuestra ruta responde en un navegador cuando la llamamos, llamamos a res.send() pasando una cadena "Enviado" para notificarnos que el código se ha llamado correctamente.

Suponiendo que nuestra configuración de SMTP sea correcta, si visitamos http://localhost:2600/email/send en nuestro navegador, después de unos segundos deberíamos recibir nuestro correo electrónico en el destinatario especificado.

Terminando

En este tutorial, aprendimos a crear una plantilla de correo electrónico utilizando los componentes de Joystick. Aprendimos cómo conectar el componente en sí mismo, aceptar accesorios y cómo diseñar la plantilla usando CSS. Luego, aprendimos cómo probar nuestra plantilla de correo electrónico en el navegador para asegurarnos de que se veía bien y, finalmente, cómo enviarlo usando email.send() a través del servicio SMTP Matasellos.