...
Si queremos enviar correos desde el backend de nuestras aplicaciones, podemos formar el cuerpo de estos utilizando Thymeleaf. Éste es un motor de creación de plantillas html, que proporciona algunos atributos especiales para su construcción, lo que nos facilitará crear plantillas para los emails que queramos enviar, pudiendo editarlos viendo el resultado, y teniendo una mejor organización en nuestro proyecto. Vamos a ver en primer lugar la configuración y un ejemplo de uso, y después pasaremos a ver algunos de los atributos especiales que proporciona.
Configuración
En primer lugar, tendremos que añadir las siguientes dependencias a nuestro pom.xml:
| Bloque de código | ||
|---|---|---|
| ||
<!-- Thymeleaf --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4<springsecurity5</artifactId> <version>3.0.45.RELEASE</version> </dependency> |
...
| Bloque de código | ||
|---|---|---|
| ||
package es.um.atica.nombreproyecto.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.StringTemplateResolver;
@Configuration
public class MailConfig {
@Bean
public ResourceBundleMessageSource emailMessageSource() {
final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename( "mail/MailMessages" );
return messageSource;
}
@Bean
public TemplateEngine emailTemplateEngine() {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
// Resolver for HTML editable emails (which will be treated as a String)
templateEngine.addTemplateResolver( templateResolver() );
// Message source, internationalization specific to emails
templateEngine.setTemplateEngineMessageSource( emailMessageSource() );
return templateEngine;
}
private ITemplateResolver templateResolver() {
final StringTemplateResolver templateResolver = new StringTemplateResolver();
templateResolver.setOrder( 1 );
templateResolver.setTemplateMode( TemplateMode.HTML );
templateResolver.setCacheable( false );
return templateResolver;
}
} |
Plantillas
Las plantillas en nuestro proyecto serán archivos html y se encontrarán en la carpeta src/main/resources/templates. Por defecto, Thymeleaf parte de esa ruta, a partir de ahí podemos organizar los archivos como queramos. Un ejemplo de plantilla sería el siguiente:
...
Ahí especificamos una serie de variables, que vamos a ver cómo asignarlas en la parte Java.
Uso de la plantilla
Para utilizar la plantilla y obtener el String correspondiente al mensaje, siguiendo con la plantilla anterior, lo haríamos así:
...
Como vemos, utilizamos el Context de Thymeleaf (cuidado no nos equivoquemos al importarlo), establecemos los valores de las variables, y lo procesamos para obtener el String. En este caso, el archivo email.html se encuentra en la ruta base que hemos mencionado anteriormente. Si se encontrase en una subcarpeta, la ruta seguiría siendo respecto a esa ruta base, seríe "carpeta/email.html".
Atributos de Thymeleaf
Veamos los principales atributos que podremos usar: enlazar variables y renderización condicional.
Enlazar variables
Es el caso que hemos visto en el ejemplo anterior. Especificamos la variable con ${variable}, y para indicar que se renderice el texto correspondiente, lo hacemos incluyendo th:text:
...
Podemos leer más sobre esta sintaxis en la documentación oficial.
Recorrer una lista
El equivalente a un for each en nuestras plantillas sería th:each. Este es el atributo para iterar sobre una lista, y su sintaxis sería la siguiente:
...
En este caso recorremos la lista que se pase como ${prods}, teniendo en prod el objeto y en iterStat estadísticas sobre la iteración, como el índice actual o el total de iteraciones.
Renderización condicional: if, unless, switch
Con th:if haremos que el elemento se renderice si el valor que pasamos es true:
...