src/main/resources/email-templates/sales-report/template.html:

<table style="border:solid 3px; border-color:#e4701e; border-radius:10px;">
  <caption style="font-size:14px; font-weight:bold;">SALES BY COUNTRY</caption> 
    <thead>
      <tr>
        <th>Country</th>
        <th>Sales amount</th>
      </tr>
  </thead>
  <tbody>
    <tr th:each="sales, status : ${salesByCountry}" th:style="${status.odd} ? 'background: #f0f0f2;' : 'background: #ffffff;'">
      <td th:text="${sales.key}" />
      <td style="text-align:center;" th:text="${#numbers.formatCurrency(sales.value)}" />
    </tr>
    <tr style="background:#dddddd;">
      <td colspan="2" style="text-align:right; font-weight:bold;">Total: <span th:text="${#numbers.formatCurrency(totalSales)}"></span></td>
    </tr>
  </tbody>
</table>

<p>
  <img th:src="|cid:${imageCompanyLogo}|" />
</p>


EmailRepository.java:

private final ISpringTemplateEngine thymeleafTemplateEngine;

@Value("classpath:/email-templates/Asimio-Tech-Logo.png")
private Resource companyLogo;
// ...

public Email create(SalesReport salesReport, List<String> recipients) {
  Context ctx = new Context(Locale.US);
  ctx.setVariable("salesByCountry", salesReport.getSalesByCountry());
  ctx.setVariable("totalSales", totalSales);
  ctx.setVariable("imageCompanyLogo", "imageCompanyLogo");
// ...

  String htmlContent = this.thymeleafTemplateEngine.process("sales-report/template.html", ctx);
  String textContent = this.thymeleafTemplateEngine.process("sales-report/template.txt", ctx);

  Map<String, Resource> embeddedResources = new HashMap<>();
  embeddedResources.put("imageCompanyLogo", this.companyLogo);

  return Email.builder()
// ...
    .html(htmlContent)
    .text(textContent)
    .inlines(embeddedResources)
    .build();
}


MessagingService.java:

private final JavaMailSender mailSender;

public void sendEmail(Email email) {
  MimeMessage message = this.mailSender.createMimeMessage();
  try {
    // MULTIPART_MODE_MIXED to support embedding/inlining resources
    MimeMessageHelper messageHelper = new MimeMessageHelper(
      message,
      MimeMessageHelper.MULTIPART_MODE_MIXED,
      "UTF-8"
    );

    // Set plain and/or html content
    if (email.getHtml() == null) {
        messageHelper.setText(email.getText());
    } else {
        messageHelper.setText(email.getText(), email.getHtml());
    }

    // Embedded resources
    if (!CollectionUtils.isEmpty(email.getInlines())) {
      email.getInlines().forEach((contentId, source) -> {
        try {
          Path path = Path.of(source.getFilename());
          String contentType = Files.probeContentType(path);
          messageHelper.addInline(contentId, source, contentType);
        } catch (MessagingException | IOException ex) {
          log.warn("Logging and rethrowing messaging exception", ex);
          throw new SendMessageException(ex.getMessage());
        }
      });
    }

    // Send message
    this.mailSender.send(message);
  } // End try
// ...
}


Usage

Email salesReportEmail = this.emailRepository.create(salesReport, recipients);
this.messagingService.sendEmail(salesReportEmail);


HTML Email using Spring Boot and Thymeleaf HTML Email using Spring Boot and Thymeleaf