Envío de Email con Firebase Functions y Nodemailer
Tags: firebase, node, googlecloud, react
Published: 2023-06-21 18:21:52

En esta publicación trataré de explicar el uso de Firebase Functions junto a Nodemailer para el envío de correos electrónicos. Actualmente estoy trabajando en un proyecto que se requiere la implementación de una funcionalidad que envíe un correo al realizar una acción como es el registro por formulario de un usuario. A continuación explicaré los pasos para la implementación.

**Instalación**

**Consideración 1:** Para este caso usaremos un [proyecto React](https://create-react-app.dev/docs/getting-started) para el formulario de registro.

**Consideración 2:** Antes del primer paso, se asume que ya se cuenta con un [proyecto creado de firebase](https://cloud.google.com/firestore/docs/client/get-firebase?hl=es-419).

**Paso 1:** Instalación de Firebase CLI

Para poder usar todas las funcionalidades de Firebase en nuestro proyecto, tenemos que instalar via NPM las dependencias y funcionalidades. En la terminal ingresamos el siguiente comando:

```
npm install -g firebase-tools
```
Después de instalar, iniciamos sesión con nuestra cuenta de Google Firebase mediante el siguiente comando:

```
firebase login
```
**Paso 2:** Inicializando el proyecto desde Firebase

Después de iniciar sesión en Firebase, ejecutaremos el comando para iniciar con la configuración y crear la función. Ingrese el siguiente comando en la raíz del proyecto:

```
firebase init
```
Nos mostrará una lista de todos los servicios que tiene Firebase, en este caso seleccionaremos Functions(recuerda navegar por comando con las flechas de arriba y abajo, seleccionar con ‘space’ y continuar con ‘enter’):

![firebase tools](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93uj1lebjvsmraukipub.png)

Después, seleccionamos un proyecto ya existente en firebase(en caso contrario puedes crear primero el proyecto en Firebase console como lo expliqué lineas arriba):


![Seleccionar proyecto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/od43bgaokfulnchgwnkz.png) 

Seleccionamos nuestro proyecto de prueba:

![Proyecto seleccionado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jhmzao5thxm2bfm0phge.png)

y a continuación nos solicitará en que lenguaje queremos instalar(en este caso usaremos **JavaScript**), después nos consultará por el uso de **ESLint** para capturar posibles bugs, en este caso tampoco lo usaremos y finalmente nos solicitará la instalación de dependencias necesarias desde NPM, en este caso le daremos en **sí**.

Finalmente tendremos instalado una nueva carpeta llamada functions donde trabajaremos en el archivo index.js
   

![Functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6j0t4f8e6z8llwfyf6e.png)

**Paso 3:** Configuración de Functions Firebase en el index.js

Antes debemos instalar la dependencia de [Nodemailer](https://nodemailer.com/about/), para eso usamos la linea de comando y nos vamos hasta la carpeta functions y ejecutamos el siguiente comando:

```
npm install nodemailer
```
Después de instalarlo, podemos continuar con el primer paso en el archivo **index.js** de la functions, para eso importamos la dependencia de firebase-functions y nodemailer:

```
const functions = require("firebase-functions");
const nodemailer = require("nodemailer");
```

Creamos la función **transport** donde agregaremos el servicio de correo electrónico que usaremos y las credenciales de autentificación(en las ultimas políticas de Google, se pide crear una contraseña de aplicaciones para poder acceder a Gmail desde un servicio de terceros, créalo [de esta manera](https://support.google.com/accounts/answer/185833?hl=es-419) ) 

```
const transport = nodemailer.createTransport({
   service: "Gmail",
   auth: {
      user: "user@gmail.com",
      pass: "hkjUIjhkKBJHkjadfg",
   },
});
```
Después, creamos una función que se activará al crear una nueva colección en firebase:

```
exports.emailSuccess = functions.firestore
   .document("userRegister/{id}")
   .onCreate(async (snap) => {
      const getData = snap.data();
      const email = await getData.email;
      return sendSuccess(email);
   });
```
el **userRegister** viene a ser la colección donde estamos guardando los usuarios registrados desde un formulario y nuestra función se activará cada vez que exista un nuevo registro o **snap**.

Capturamos el atributo **email** que fue registrado desde el formulario y lo mandamos como parámetro a la función sendSuccess.

Finalmente creamos la etiqueta HTML dentro de la función sendSuccess de la siguiente manera:

```
const sendSuccess = (email) => {
   return transport
      .sendMail({
            from: "Napster.dev <napster@gmail.com>",
            to: email,
            subject: "Hola mundo",
            html: `
            <!DOCTYPE html>
               <html lang="en">
               <head>
                  <meta charset="UTF-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                  <title>Email de ejemplo</title>
               </head>
               <body style="font-family: Arial, sans-serif;">
                  <table style="width: 100%; max-width: 600px; margin: 0 auto; border-collapse: collapse;">
                     <tr>
                           <td style="background-color: #f1f1f1; padding: 20px; text-align: center;">
                              <h1>Bienvenido al ejemplo de correo electrónico</h1>
                           </td>
                     </tr>
                     <tr>
                           <td style="padding: 20px;">
                              <p>Hola,</p>
                              <p>Este es un correo electrónico de ejemplo.</p>
                           </td>
                     </tr>
                  </table>
               </body>
               </html>
               `,
      })
      .then((r) => r)
      .catch((e) => e);
};
```
Para el despliegue de la función en firebase, ingresamos el siguiente comando:

```
firebase deploy --only functions 
```

Esto hará desplegar solo la carpeta functions(Recuerda que para hacer el despliegue tienes que tener un plan Blaze de pago en firebase ).

Este es el código completo:

```
const functions = require("firebase-functions");
const nodemailer = require("nodemailer");

const transport = nodemailer.createTransport({
   service: "Gmail",
   auth: {
      user: "user@gmail.com",
      pass: "hkjUIjhkKBJHkjadfg",
   },
});

exports.emailSuccess = functions.firestore
   .document("userRegister/{id}")
   .onCreate(async (snap) => {
      const getData = snap.data();
      const email = await getData.email;
      return sendSuccess(email);
   });

const sendSuccess = (email) => {
   return transport
      .sendMail({
            from: "Napster.dev <napster@gmail.com>",
            to: email,
            subject: "Hola mundo",
            html: `
            <!DOCTYPE html>
               <html lang="en">
               <head>
                  <meta charset="UTF-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                  <title>Email de ejemplo</title>
               </head>
               <body style="font-family: Arial, sans-serif;">
                  <table style="width: 100%; max-width: 600px; margin: 0 auto; border-collapse: collapse;">
                     <tr>
                           <td style="background-color: #f1f1f1; padding: 20px; text-align: center;">
                              <h1>Bienvenido al ejemplo de correo electrónico</h1>
                           </td>
                     </tr>
                     <tr>
                           <td style="padding: 20px;">
                              <p>Hola,</p>
                              <p>Este es un correo electrónico de ejemplo.</p>
                           </td>
                     </tr>
                  </table>
               </body>
               </html>
               `,
      })
      .then((r) => r)
      .catch((e) => e);
};
```