Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Contenidos Mediante Google Apps Script podemos almacenar información, modificarla o incluso
crearla sin utilizar las intefaces clásicas de los servicios , por ejemplo ,un documento en
1 El lenguaje Google Script
Drive. Los servicios que solemos utilizar , documentos , hojas de cálculo, gmail, etc,
1.1 Editor de Comandos. disponen de una serie de APIs ( Application Programming Interface ) que son un conjunto
1.2 Primer Script de subrutinas de código, que no podemos modificar, pero sí utilizar, mediante otro
1.3 Tipos de scripts: programa de software, a través de sus métodos y propiedades. En el caso de Google Apps
1.4 Depuración del código Script utiliza la sintaxis de JavaScript, y los programas creados permitirán manipular la
1.5 Activadores de scripts. información de los servicios antes mencionados.Por ejemplo, podemos acceder a la
2 Scripts en Spreadsheets. información de una hoja de cálculo y enviarla, de manera automatizada y programada en
el tiempo, a direcciones de correo.
2.1 Añadir menú a una hoja de cálculo
2.2 Mostrar información en H. de Cálculo
Los programas se crean utilizando las comentadas APIs, y se ejecutan en los servidores
2.3 Acceso a la información de las celdas . de Google, es decir del lado del servidor, a diferencia del JavaScript tradicional que es
3 El servicio GMail interpretado por los navegadores del lado del cliente.Los servicios que podemos utilizar en
3.1 API GmailApp. nuestros scripts son los usuales : Sites, Maps, Google Apps Services , como Calendar,
3.2 getDraftMessages() Contacts, documents, www, drive, gmail, groups . ; y oros más avanzados como adsense ,
3.3 sendMail() urlshortener, analytics,..... Se pueden ver , estando en el Editor, en el menú Recursos >
3.4 Texto HTML como body de un correo. Servicios avanzados de Google
Editor de Comandos.
La forma más adecuada para ver ejemplos de Google Script tal vez sea las hojas de cálculo. Dentro de nuestra cuenta de Google , vamos a Drive y
creamos un nuevo documento del tipo "Hojas de Cáculo".
Nos aparece el nuevo documento sin nombre, y al desplegar el menú Herramientas , elegimos "Editor de secuencias de Comandos", de la nueva
ventana elegimos "Proyecto en Blanco" ( ver figura siguiente)
En la imagen inferior muestra el Editor de comandos. Nos indica "Proyecto sin titulo" que podemos nombrar haciendo clic y nombrando el proyecto.Un
proyecto consta como mínimo de un archivo de código , que por defecto se nombra como "Código.gs"; pero se puede cambiar; basta con hacer clic en el
desplegable a la derecha del nombre Código.gs , y el menú emergente nos da tres opciones: Eliminar, Hacer una copia , y Cambiar nombre. En la
parte de la derecha iremos escribiendo el código de nuestro script, que por defecto nos da el inicio function myFunction(){.....
En la parte superior tenemos la barra de menús: Archivo Editar Ver Ejecutar Publicar Recursos Ayuda. Debajo del menú aparecen iconos de
acciones concretas.
En el menú Archivo están las acciones típicas : Guardar, Borrar, Nuevo, Abrir, Revisiones, etc
En Editar , tenemos : Deshacer, Rehacer, Seleccionar, Buscar y reemplazar, etc. Aquí tenemos la opción de activar "Asistencia de contenido", que
nos ayudará al hora de escribir el código, ya que nos adelanta las siguientes opciones que podemos tomar sin necesidad de escribir el comando.
En Ver , existe: Transcripción de la ejecución ( nos indica todos los estados por los que va pasando el programa en los sucesivos pasos) ; y
Registros ( se utiliza cuando estamos haciendo pruebas de ejecución o depuramiento).
En Ejecutar : nos da la opción de ejecutar algún archivo de código que tengamos.
En Publicar : tenemos la opción de "publicar" nuestro script en la red y se ejecutará accediendo a él mediante su URL publicada.
Recursos : desde aquí podemos programar en el tiempo la ejecución del script , mediante ciertos eventos.
En el menú Ayuda : información relacionada con el tema
Como se ve el menú es similar al de cualquier documento de Google. Como se menciona anteriormente, la opción de Asistencia de contenido es una
muy buena herramienta; por ejemplo en el script en que estamos , nos situamos debajo de la primera linea y empezamos a escribir var a = ; si
después del = pulsamos CTRL+Barra esp. , veremos que nos muestran las posibilidades de elegir lo que podríamos poner a continuación.
La opción de Asistencia de Contenido es un buen método de escritura para evitar errores en el texto del código, pero sobre todo nos facilita , en cada
momento, los métodos posibles.
Por ejemplo, imaginemos que en una linea tenemos que teclear el siguiente código :
SpreadsheetApp.getActiveSpreadsheet().deleteActiveSheet() ; sería probable cometer algún error ortográfico y fallar la ejecución. En el
Proyecto sin titulo anterior, en la linea 2 empezamos a escribir una s y pulsamos CTRL+ BarraEsp., aparece una ventana emergente con las
sugerencias de lo que puedo escribir (Figura izquierda). Hay que recordar que se diferencian mayúscula y minúsculas ; Por ejemplo,
getActivespreadsheet() , será una función desconocida y no se ejecutaría el código
Entre las sugerencias aparece la "palabra" SpreadsheetApp ; la seleccionamos haciendo clic sobre ella . Al escribir el . ( punto) ,nos muestra las
siguientes sugerencias,que son los métodos de la clase SpreadsheetApp ( Fig central); seleccionamos el método que necesitamos, y así sucesivamente
Primer Script
Como primer ejemplo vamos a escribir el siguiente código, ( primero borramos las tres lineas del código existente)
Se trata de un código de 4 lineas; empieza con la palabra reservada function , con el nombre que damos a la función seguida de () - o bloque de
código- , una llave de apertura { , para indicar las lineas de código que conforman el bloque, 2 lineas de código que terminan en un un ; , y la llave de
cierre }.Esta es la estructura básica de un bloque .
En la linea 2 se define una variable con la palabra reservada var y de nombre valor , con el signo = le asignamos un valor a esa variable , que se
empieza a construir a partir de la API (clase del lenguaje) SpreadsheetApp; de esa clase se toma su método getActiveSpreadsheet(), que hace relación a
documento de Hoja de cálculo abierto, y de ese documento se toma la hoja activa , mediante le método getActiveSheet() , , y de esa hoja se define el
rango formado por la celda A2 , y se toma el valor de esa celda: todo eso para indicar que el valor de la celda A2 de la hoja activa del documento activo
del tipo Hoja de cálculo se pasa a la variable valor .
A la vez que se va escribiendo el código, Google hace un recorrido a través del mismo para indicar si hay errores de sintáxis . Si no se indican , no es
señal que el código sea correcto o que se produzcan los resultados que deseamos
La linea 3 indica que haga uso del método log de la clase Logger , para que ponga el valor de la variable valor en los registros - o lugares que sean
visibles para nosotros-
Si se observa la existencia de un asterisco rojo al lado del nombre del fichero de código: significa que debemos guardar el fichero . Para guardar
Archivo > Guardar , o bien CTRL +S . o bien clic en el icono :
Si queremos ejecutar el código pulsamos el botón de ejecutar- segundo de los anteriores- nos pedirá autorización, aceptamos .Para ver que el código
produce algo , deberemos ir a la hoja de cálculo e insertar algo en la celda A2.
Si ejecutamos el script veremos que el valor de la celda A2 de la hoja de cálculo se ha recogido en el registro , como se comprueba al ir a Ver >
Registros . Con este pequeño ejemplo ,se ve cómo se puede manipular la información de uno de los servicios de Google, como son los Hojas de
cálculo.
es un bloque de código de lineas JavaScript englobado entre dos {.... código ... }
empieza con la palabra reservada function , y seguido del nombre de esa funcion
cada linea termina en un ;
Utiliza APIs con sus métodos unidos mediante .
El editor nos detecta los errores de sintaxis, pero pueden existir errores en tiempo de ejecución.
Apps Script está basado en el lenguaje JavaScript , y no se ejecuta en el navegador del cliente ( salvo el código basado en la API HTML services) .
Podrá utilizar instancias de objetos tales como Array, Date,.. ( ver aquí )
Tipos de scripts:
Standalone : este tipo de código se ejecutan de manera manual, y está asociado a los documentos de Drive. También tienen la posibilidad de
"publicar" , en el sentido que se puede acceder a ese código mediante una URL; en estos casos se necesitan permisos para acceso a las aplicaciones
que el código maneja y también para los usuarios que vaya a utilizar ese código. El ejemplo anteriormente explicado sería de ese tipo: requiere de una
acción manual para su ejecución
Integrados ( container bound script) en aplicaciones como Formularios, Hojas de cálculo, Google Documents . Se utilizan para dar una mayor
funcionalidad a esas aplicaciones.
A medida que escribimos el código el editor nos informa de los errores sintácticos, indicando el tipo de error y en qué linea , mediante un mensaje con
fondo rojo en la parte superior del Editor . Pero pueden existir errores solo detectados cuando se ejecuta el código o bien no hay errores pero no se producen
los resultados esperados, por eso es necesario el proceso de depuración. Abrimos nuestro script y escribimos el siguiente código
function errores(){
var hc = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var x = dato;
hc.getRange(6, 2).setValue(x);
}
Veremos que el editor no nos informa de ningún error,pero si se ejecuta nos informa de que hay un error , la variable dato no está definida .Si queremos
más información de los fallos de código , se elige la función y se pulsa el botón de depurar.
Para tratar los errores se utiliza el par de sentencias try/catch . Modificamos el código anterior por el siguiente:
function errores(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
try{
var x = dato;
ss.getRange(2, 6).setValue(x);
}catch(e){
Logger.log(e.name+' en la linea :'+e.lineNumber+'=>'+e.message);
}
}
Al ejecutar no da error , no se cumple el propósito que era poner un valor en la celda (F,2) el valor de la variable dato.No da aviso de error ya que este ha
sido capturado en la parte catch . Ya que se utiliza el método log , tendremos información del error en el Registro. En este caso bastaría darle a x un valor. Si
ejecutamos la función errores() , ya nos hay errores , es decir se ejecuta el bloque try
Activadores de scripts.
Los ejemplos de funciones anteriores requerían una acción manual para su ejecución, pero existe la posibilidad de que se ejecuten de manera automática,
según qué tipo de eventos sucedan. Por ejemplo, más adelante se utilizará la función onOpen() , que se ejecutará de manera automática al abrir la hoja de
cálculo que integrante del scrip que incluya esa función.Existen más funciones que responden a eventos concretos:
Como estas funciones se activan cuando suceden los eventos - abrir hoja, hacer cambios, ejecutar script, cargar una web ,..- y no se pregunta por la
autorización tiene que cumplir una serie de restricciones : estar asociadas a una documento del tipo Hoja de Cálculo, Documento o Formulario; no podrán
acceder a servicios que requieran autorización ( gmail, drive,..); tiene un tiempo limite de ejecución de 30 seg, ....
Aparte de estos Activadores de las funciones anteriores , existen otros para las funciones definidas en general. En el Editor vamos a Recursos >
Activadores del proyecto activo ; si es la primera vez nos indica que no se ha configurado ningún activador. Hacemos clic y nos aparece la opción de
configuralos
Podemos agregar más activadores para otras funciones. Tenemos que pulsar Guardar para la programación de la ejecución quede archivada.
Scripts en Spreadsheets.
Añadir menú a una hoja de cálculo
Como anteriormente he comentado la mejor forma de ver la aplicación de los scripts es aplicándolos a las Hojas de Cálculo (o Spreadsheets)
utilizando la API SpreadsheetApp , cuya documentación podemos ver https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app.
Creación de un menú : en el ejemplo siguiente se creará un menú que se añadirá a la barra de herramientas de una hoja de cálculo. Abrimos la
hoja de cálculo, y vamos Herramientas > Editor de secuencias de comandos..., y escribimos el siguiente código :
En la imagen adjunta se muestra el código prototipo para crear un menú con tres entradas. Utiliza el
método getUi de la API SpreadsheetApp; este método devuelve una instancia de la hoja de cálculo para permitir añadir menús, ventanas de dialogo
para mostrar/entrar información . Analizamos el código : se muestra en 8 lineas para mayor legibilidad, aunque consta de una única instrucción.
- En la linea 6 se define la función, que se nombra menuNuevo()
- En la siguiente linea creamos mediante getUi() una "réplica" de la hoja de cálculo
- La siguiente número 8 , con el método createMenu() , creamos un menú que lo nombramos MiMenu
- En las tres siguientes añadimos entradas al menú con el método addItem() : el primer literal es el nombre de la entrada del menú y el segundo la acción
a realizar , que será el nombre de una función que deberemos definir
- Con el método addToUi() , agregamos el menú a la hoja de cálculo . Ya que es el final de la instrucción se indica con un ;
- La última linea es para cerrar el bloque
Si ejecutamos esta función y vamos a la hoja de cálculo veremos el nuevo menú . En este caso no hay ninguna acción que vaya a realizar porque no se
ha añadido, esto se haría cerando las funciones de nombres accion1 , acciojn2 y accion3 .
Si nos fijamos en la documentación de la clase SpreadsheetApp , vemos que permite crear submenús con el método addSubMenu() , e intercalar,
opcionalmente , un separador con el método addSeparator()
El ejemplo solo muestra la creación de menú, no hay acciones asociadas a los items , además no es nada práctico ya que para que aparezca el menú
debemos lanzar manualmente el código. Podemos hacer que el menú aparezca siempre que se abra la hoja de cálculo, sin intervención manual
utilizando la función de nombre especial onOpen() , en lugar del nombre menuNuevo() : la función onOpen() , , se ejecuta cada vez que se abre la hoja
de cálculo.
Cuando se trabaja en una spreadsheet , puede ser necesario mostrar/ solicitar información al usuario, y se consigue mediante varias formas:
1.- Usando la clase Logger : en el primer scrip antes mencionado se muestra un ejemplo, utilizando el método log de dicha clase; suele
utilizarse en procesos de depuración de código para ver estados del programa , por tanto no se restringe solo al caso de hojas de cálculo . Los
resultados se muestran en "registros".Como se puede ver en su documentación la clase dispone de 4 métodos:
2.- Mediante la clase Browser ( solo para hojas de cálculo). Más información aquí . Como se ve en la documentación dispone de dos
métodos:inputBox() para recabar información y msgBox() para mostrarla, en ambos cabe la posibilidad de agregar "botones" de información ,
basados en el "tipo" enumerado ButtonSet . Por ejemplo el código Browser.msgBox('Hola', Browser.Buttons.OK_CANCEL); produciría el
siguiente mensaje.
En la imagen superior , se ha añadido la linea 15 al bloque de código del apartado anterior, y el nombre de la función, tal como se comentó, pasa a ser
onOpen() para que se ejecute al abrir la hoja. Se ve como el texto de msgBox() se muestra en la ventana emergente, y además se ha añadido el botón de
Cancelar Para el caso de inputBox() se define una variable que recoja el valor introducido.
3.- Mediante el comando throw() , válido no solo en el contesto de las hojas de cálculo tal como sucede con la clase Logger. Si en la ventana del
editor ejecutamos la linea de código throw('el valor de la variable dia es :'+fecha) ; nos aparecería en la parte superior el siguiente mensaje:
4.- Mediante el método show() de la API SpreadsheetApp, que nos mostrará en el centro de la pantalla la Interface gráfica especificada . La
generación de Interface Gráficas se verá más adelante
5.- Usando el método toast() de la clase SpreadsheetApp. toast() , admite o bien dos parámetros , o bien tres ; en este caso con el tercero se indica
el tiempo en segundos que permanecerá visible la ventana emergente. Si especificamos un número negativo , la ventana permanecerá abierta hasta
que manualmente la cerremos.El método toast() de la clase Spreadsheet tiene la siguiente sintaxis: toast(msg, title, timeoutSeconds)
Mediante el código Google Apps Script , podemos manejar la información de una hoja de cálculo.El procedimiento resumido es el siguiente.
Siguiendo con nuestro script empezado, lo modificamos con los siguientes cambios:
function onOpen(){
SpreadsheetApp.getUi()
.createMenu('MiMenu')
.addItem('Item1', 'rellenaCeldas')
.addSeparator()
.addItem('Item2', 'accion2')
.addItem('Item2', 'accion3')
.addToUi();
//var dia = 12;
//throw('el valor de la variable dia es = ' + dia);
function rellenaCeldas(){
var hc = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
for(var fila=1 ; fila<=20; fila++){
hc.getRange(fila, 1).setValue('El valor de la celda es '+fila);
}
}
Se codifica una función que llamamos rellenaCeldas() , y se asocia con la primer entrada del menú creado, MiMenu.
Los caracteres // , permiten crear comentarios para documentar el código, cuando éste es largo y de difícil comprensión; por lo tanto las dos lineas
que empiezan con // no se ejecutan ,
La variable hc hace referencia a la hoja activa del documento Hoja de Cálculo que integra el código ( bound-script )
Con el método getRange (fila,1) , hacemos referencia a cada una de las 20 primeras celdas de la columna 1
Con el método setValue(), damos valores a esas celdas.El valor que se introduce en las celdas es la cadena de texto formada por El valor de la
celda es concatenada, mediante el operador +, con el valor de la variable fila . El operador + está 'sobrecargado' es decir por ejemplo 7+8 nos
devuelve 15 , pero 7+' casas' nos devuelve 7 casas
Como he expresado, los comentarios de linea se crean con los caracteres // , por ejemplo , en la siguiente linea de código hc.getRange(fila,
1).setValue('El valor de la celda es '+fila); // se inserta el valor en la celda , el texto //se inserta el valor en la celda no sería código ejecutable, sino
solamente un comentario. Se pueden añadir bloques de lineas de texto no ejecutable mediante los caracteres /* y */ . Todas las lineas encerradas entre
esas dos marcas no se interpretan por el servidor.
En la función rellenaCeldas() , se accede durante 20 veces diferentes a la variable hc, es decir hay que hacer 20 peticiones de acceso al servidor , y
esto tiene un coste en el tiempo. Supongamos el caso en el que debemos poner en un rango de celdas un mismo valor : se podría utilizar una función
similar a rellenarCeldas() , o bien utilizando la siguiente funcion rellenaCeldas2() como vemos en el código siguiente:
function onOpen(){
SpreadsheetApp.getUi()
.createMenu('MiMenu')
.addItem('Completa celdas una a una', 'rellenaCeldas')
.addItem('Completa bloque', 'rellenaCeldas2')
.addSeparator()
.addItem('Item2', 'accion3')
.addToUi();
//var dia = 12;
//throw('el valor de la variable dia es = ' + dia);
/*
var iG = HtmlService
.createHtmlOutput('<p><b>Mensaje importante<b></p>')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('Ejemplo de Aplicación')
.setWidth(250)
.setHeight(250);
SpreadsheetApp.getActiveSpreadsheet().show(iG);
*/
function rellenaCeldas2(){
var inicio =new Date().getTime();// defino la misma variable que en la función anterior, pero son diferentes: una variable
desaparece cuando nos salimos del bloque en el que se define
var hc = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
hc.getRange(1,2,200,1).setValue('Celdas columna-2');// accedo solo una vez a todo el rango, y le pongo valores
hc.getRange(1,4).setValue(new Date().getTime()-inicio);
Explicaciones:
En el menú, he cambiado el nombre de las dos primeras entradas, y he agregado la función asociada a la segunda entrada del menú
Existe un bloque de código comentado , encerrado entre /+ y */ , por tanto no se ejecuta ( Si se descomenta , podremos ver su efecto)
Se declara una variable del tipo Date() y se recoge el tiempo en inicio . Al final del for , se vuelve a recoger el tiempo en ese instante, se resta con
el valor de inicio , y se coloca la diferencia en la celda (C,1).
Las variables definidas dentro de un bloque solo existen mientras la ejecución está en ese bloque, es decir , inicio o hc de la primera función y de
la segunda tienen valores diferentes.
En la segunda función se accede de una vez al rango, solo hay una petición al servidor.El tiempo de ejecución se recoge en la celda (D, 1).
El servicio GMail
Con toda seguridad el servicio de correo sea , si no el más utilizado , el primero que se empieza a utilizar. Google, para el manejo del correo, presenta
una interface bastante clara y con posibilidades como las diferentes bandejas,posibilidad de crear filtros, con un editor que permite crear textos con
formato , etc. Aunque Google Apps Script no ofrece una gran variedad de nuevas posibilidades, con la API GmailApp podremos sacar más provecho en
la gestión de correos. Mediante la clase GmailApp podremos acceder acceder a nuestra cuenta de Gmail y hacer mediante código las operaciones que
desde la inteface se podían realizar: acceder a los correos,crear etiquetas y enviar correos.pero existen otras clases como GmailAttachment , con la que
podemos obtener información de los archivos adjuntados a los correos, GmailLabel para manejar las etiquetas, por ejemplo podemos generar una
relación de los correos no leídos etiquetados con una cierta etiqueta; GmailMessage que nos permite recabar información del propio mensaje , por
ejemplo si es un borrador, si ha sido leído, etc, y la API GmailThread , que permite gestionar los "hilos" de los correos.
API GmailApp.
Esta clase, mediante sus métodos, nos permite acceder a los hilos de correo, a los mensajes de estos hilos y a las etiquetas. Tenemos información sobre
esta clase en la siguiente dirección . Es importante saber qué objeto "devuelve" cada uno de los métodos de esta API; por ejemplo el método
createLabel("nombreEtiqueta") nos devuelve un objeto de la clase GmailLabel y por tanto se le podrán aplicar los métodos de dicha clase, o el
método getInboxUnreadCount() nos devuelve un tipo nativo INTEGER , que podré sumar con otro entero,o el método getAliases() , nos devuelve un
array donde sus elementos son los alias de la cuenta.
Veamos algunos métodos:
getDraftMessages()
En el scrip el método
getDraftMessage() , nos
devuelve un valor del tipo array
,que recogemos en la variable
borradores; este array tiene una
serie de métodos [ si utilizamos
la opción de Asistencia de
contenido , nos los presenta el
editor]; que podemos utilizar :
Ejemplos.
Con este método podemos enviar correos. En el método podemos explicitar 3 o 4 parámetros; los obligatorios son : receptor, asunto y body , y en el
cuarto permite opciones extras.La sintaxis básica será : GmailApp.sendMail(eMail, asunto,body), en donde eMail, asunto y body serán cadenas de texto,
o variables cuyos valores sean texto. El texto del correo no puede exceder de 20kB( no se tienen en cuenta el tamaño de los adjuntos)
Vamos a ver como enviamos un correo con un fichero adjunto del tipo .pdf, utilizando la opción attachments .
Como se ha comentado en la función sendMail() ,mediante la cuarta opción podemos expresar una lista de parámetros, uno de ellos es la posibilidad de
adjuntar un documento a un correo; otra es la de enviar como body un texto con marcas HTLM. Para esto utilizaremos la opción htmlBody de la anterior
función y la API HtmlService . Esta clase se utiliza para que un script pueda producir código HTML para ser enviado al navegador ( por motivos de
seguridad no se puede enviar código desde un script al navegador). La clase a través de sus métodos, filtra el código html producido y evita código
malicioso . Además necesitaremos una plantilla, que será un fichero .html, que se utilizará como base del body del correo.
El fichero plantilla , lo creamos desde el Editor : Archivo > Nuevo > Archivo HTML .
Para crear la plantilla utilizaremos la siguiente linea de código : var plantilla = HtmlService.createHtmlOutputFromFile('nombre del fichero html
creado'); Se indica en la siguiente función enviaCorreo3():
Podemos incluir también estilos CSS , situándolo entre las etiquetas <style> y </style>.
Tambien podemos crear un "fichero de estilo" externo .El fichero .css se crea de lamisma manera que el .html. Si el fichero .css creado tiene por nombre
estilo.css podemos invocarlo desde el fichero .html con la siguiente linea:
<?!=HtmlService.createHtmlOutputFromFile('estilo').getContent();?>
Dicha linea es sustituida por el contenido del fichero especificado al ejecutarse el código
function enviaCorreo3(){
var nombre=" Tu nombre y apellidos";
var template = HtmlService.createTemplateFromFile('ejemplo'); // ejemplo es el nombre del fichero html creado
// template.nombre=nombre;// en el caso que haya
//Logger.log(template.evaluate().getContent()); // para probar código
GmailApp.sendEmail('ticIKT@artazaromo.com', "Prueba con plantilla","", {htmlBody:template.evaluate().getContent()})
}
Mediante ese código podemos dar un formato más versátil al correo, por ejemplo las etiquetas <div> o <table> nos proporcionan un buen método para
maquetar el texto si se les aplica un estilo adecuado.