Utilizzo dei modelli di email ThymeLeaf e FreeMarker con Spring

1. Panoramica

Nel nostro articolo precedente, abbiamo visto come utilizzare Spring per scrivere e inviare messaggi di posta elettronica di testo.

Ma è anche possibile utilizzare i motori di modelli Spring per scrivere bellissime email HTML con contenuto dinamico .

In questo tutorial impareremo come farlo utilizzando i più famosi di loro: Thymeleaf e FreeMarker .

2. Email HTML di primavera

Cominciamo dal tutorial Spring Email.

Innanzitutto, aggiungeremo un metodo alla classe EmailServiceImpl per inviare e-mail con un corpo HTML:

private void sendHtmlMessage(String to, String subject, String htmlBody) throws MessagingException { MimeMessage message = emailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); helper.setTo(to); helper.setSubject(subject); helper.setText(htmlBody, true); emailSender.send(message); }

Stiamo usando MimeMessageHelper per popolare il messaggio . La parte importante è il vero valore passato al metodo setText : specifica il tipo di contenuto HTML.

Vediamo ora come costruire questo htmlBody usando i template Thymeleaf e FreeMarker.

3. Configurazione foglia di timo

Cominciamo con la configurazione. Possiamo isolarlo in una classe chiamata EmailConfiguration .

Per prima cosa, dovremmo fornire un risolutore di modelli per individuare la directory dei file dei modelli .

3.1. Modelli come risorse del percorso di classe

I file modello possono essere spediti all'interno del file JAR , che è il modo più semplice per mantenere la coesione tra i modelli ei relativi dati di input.

Per individuare i modelli dal JAR, utilizziamo ClassLoaderTemplateResolver . I nostri modelli si trovano nella directory principale / resources / mail-templates , quindi impostiamo l' attributo Prefix relativo alla directory delle risorse :

@Bean public ITemplateResolver thymeleafTemplateResolver() { ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setPrefix("mail-templates/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode("HTML"); templateResolver.setCharacterEncoding("UTF-8"); return templateResolver; }

3.2. Modelli da directory esterna

In altri casi, potremmo voler modificare i modelli senza dover ricostruire e distribuire . Per ottenere ciò, possiamo invece mettere i modelli sul filesystem.

Potrebbe essere utile configurare questo percorso in application.properties in modo da poterlo modificare per ogni distribuzione. È possibile accedere a questa proprietà utilizzando l' annotazione @Value :

@Value("${spring.mail.templates.path}") private String mailTemplatesPath;

Quindi passiamo questo valore a un FileTemplateResolver , al posto di ClassLoaderTemplateResolver nel nostro metodo thymeleafTemplateResolver :

FileTemplateResolver templateResolver = new FileTemplateResolver(); templateResolver.setPrefix(mailTemplatesPath);

3.3. Configura il Thymeleaf Engine

Il passaggio finale è creare il metodo di fabbrica per il motore Thymeleaf. Dovremo dire al motore quale TemplateResolver abbiamo scelto, che possiamo iniettare tramite un parametro al metodo bean factory:

@Bean public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); templateEngine.setTemplateEngineMessageSource(emailMessageSource()); return templateEngine; }

Qui, il resolver che abbiamo creato in precedenza viene iniettato automaticamente da Spring nel metodo factory del motore di modelli.

4. Configurazione FreeMarker

Allo stesso modo di Thymeleaf, nella classe EmailConfiguration , configureremo il risolutore di modelli per i modelli FreeMarker (.ftl ) :

E questa volta, la posizione dei modelli verrà configurata nel bean FreeMarkerConfigurer .

4.1. Modelli nel Classpath

Qui abbiamo le stesse opzioni di Thymeleaf. Configuriamo i modelli come risorse del percorso di classe:

@Bean public FreeMarkerConfigurer freemarkerClassLoaderConfig() { Configuration configuration = new Configuration(Configuration.VERSION_2_3_27); TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/mail-templates"); configuration.setTemplateLoader(templateLoader); FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); freeMarkerConfigurer.setConfiguration(configuration); return freeMarkerConfigurer; }

4.2. Modelli nel file system

Per configurare i modelli da un altro percorso nel filesystem, dovremo sostituire l' istanza di TemplateLoader :

TemplateLoader templateLoader = new FileTemplateLoader(new File(mailTemplatesPath));

5. Localizzazione con Thymeleaf e FreeMarker

Per gestire le traduzioni con Thymeleaf, possiamo specificare un'istanza MessageSource al motore :

@Bean public ResourceBundleMessageSource emailMessageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("mailMessages"); return messageSource; }
@Bean public SpringTemplateEngine thymeleafTemplateEngine() { ... templateEngine.setTemplateEngineMessageSource(emailMessageSource()); ... }

Quindi, creeremmo bundle di risorse per ogni lingua supportata:

src/main/resources/mailMessages_xx_YY.properties

Poiché FreeMarker propone la localizzazione duplicando i modelli , non è necessario configurare lì l'origine del messaggio.

6. Contenuto dei modelli di foglia di timone

Successivamente, diamo un'occhiata al file template-thymeleaf.html :

Come si può vedere, abbiamo usato la notazione Thymeleaf, cioè $ {…} per le variabili e # {…} per le stringhe localizzate .

Poiché il motore del modello è configurato correttamente, è molto semplice da usare: creeremo semplicemente un oggetto Context che contiene le variabili del modello (passato come mappa qui).

Quindi, lo passeremo al metodo di processo insieme al nome del modello:

@Autowired private SpringTemplateEngine thymeleafTemplateEngine; @Override public void sendMessageUsingThymeleafTemplate( String to, String subject, Map templateModel) throws MessagingException { Context thymeleafContext = new Context(); thymeleafContext.setVariables(templateModel); String htmlBody = thymeleafTemplateEngine.process("template-thymeleaf.html", thymeleafContext); sendHtmlMessage(to, subject, htmlBody); }

Ora vediamo come fare la stessa cosa con FreeMarker.

7. Contenuti dei modelli FreeMarker

Come si può vedere, la sintassi di FreeMarker è più semplice, ma ancora una volta non gestisce stringhe localizzate. Quindi, ecco la versione inglese:

Hi ${recipientName}

${text}

Regards,

${senderName} at Baeldung

Quindi, dovremmo usare la classe FreeMarkerConfigurer per ottenere il file modello e, infine, FreeMarkerTemplateUtils per iniettare dati dalla nostra mappa :

@Autowired private FreeMarkerConfigurer freemarkerConfigurer; @Override public void sendMessageUsingFreemarkerTemplate( String to, String subject, Map templateModel) throws IOException, TemplateException, MessagingException { Template freemarkerTemplate = freemarkerConfigurer.getConfiguration() .getTemplate("template-freemarker.ftl"); String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel); sendHtmlMessage(to, subject, htmlBody); }

Per andare oltre, vedremo come aggiungere un logo alla nostra firma di posta elettronica.

8. Email con immagini incorporate

Poiché è molto comune includere immagini in un'e-mail HTML, vedremo come farlo utilizzando un allegato CID.

The first change concerns the sendHtmlMessage method. We have to set MimeMessageHelper as multi-part by passing true to the second argument of the constructor:

MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

Then, we have to get the image file as a resource. We can use the @Value annotation for this:

@Value("classpath:/mail-logo.png") Resource resourceFile;

Notice that the mail-logo.png file is in the src/main/resources directory.

Back to the sendHtmlMessage method, we'll add resourceFile as an inline attachment, to be able to reference it with CID:

helper.addInline("attachment.png", resourceFile);

Finally, the image has to be referenced from both Thymeleaf and FreeMarker emails using CID notation:

9. Conclusione

In questo articolo, abbiamo visto come inviare e-mail Thymeleaf e FreeMarker, incluso il contenuto HTML ricco.

Per concludere, la maggior parte del lavoro è legato alla Primavera; quindi, l'utilizzo dell'uno o dell'altro è abbastanza simile per una semplice esigenza come l'invio di email .

Come sempre, il codice sorgente completo degli esempi può essere trovato su GitHub.