Introduction

There can be many reasons to send emails from a web server:

  • send a confirmation link upon user registration

  • send a password reset link

  • ask for confirmation on sensitive operations

  • send user-submitted content to a company email, e.g. for customer support or feedback

The Yada Framework approach to emails is similar to writing a web page: an html template is populated with values before being sent via a SMTP server you have configured. I18n is also available.

Configuration

The configuration file holds the SMTP server configuration and other parameters:

<email>
        <enabled>true</enabled>
        <from>mysender@gmail.com</from>
        <logoImage>/template/email/mycompany-logo.png</logoImage>
        <smtpserver>
                <host>smtp.example.com</host>
                <port>587</port>
                <protocol>smtp</protocol>
                <username>${smtpserver_username}</username>
                <password>${smtpserver_password}</password>
                 <!--  If sendpartial is set to true, and a message has some valid and some invalid addresses, send the message anyway,
                       reporting the partial failure with a SendFailedException. If set to false (the default), the message
                       is not sent to any of the recipients if there is an invalid recipient address.  -->
                <properties>mail.smtp.sendpartial=true</properties>
                <properties>mail.smtp.auth=true</properties>
                <properties>mail.smtp.starttls.enable=true</properties>
                <properties>mail.smtp.quitwait=false</properties>
		<!-- Set this option to your mail server if you trust it and don't care checking the certificate validity, e.g. it is on your localhost
		<properties>mail.smtp.ssl.trust=email-smtp.eu-central-1.amazonaws.com</properties>
		-->
        </smtpserver>
        <!-- Remove this list to enable email to everyone -->
        <validEmail>mydeveloper1@gmail.com</validEmail>
        <validEmail>mydeveloper2@gmail.com</validEmail>
        <!-- Email patterns of invalid emails (rejected on registration) -->
        <blacklistPattern>.*invalid.*</blacklistPattern>
        <blacklistPattern>.*@mailinator.com</blacklistPattern>
</email>
enabled

when false or not set, emails are not sent

from

email address of the sender, usually a system account. Can be repeated to have more sender emails.

logoImage (optional)

path of the logo to place in the email, relative to the resources folder

host

SMTP server address

port

SMTP server port

protocol

SMTP server protocol

username

SMTP server login username. The ${smtpserver_username} value is a reference to a value stored in another configuration file, usually under /srv/xxx/bin/security.properties

password

SMTP server login password. The ${smtpserver_password} value is a reference to a value stored in another configuration file, usually under /srv/xxx/bin/security.properties

properties (optional)

list of java mail properties

validEmail (optional)

list of authorized destination emails. When present, all emails to addresses not listed here are not sent. Useful in development and test environments to prevent sending fake emails to real users

blacklistPattern (optional)

Regex patterns of email addresses that are not accepted at registration

Email Templates

Email content is defined using HTML templates as for web pages. Templates must be saved in the src\main\resources\template\email folder as html files. You can use most of the standard Thymeleaf notation, considering that neither the Model nor the HTTP request are available. Singleton beans ${@mybean} and localized strings #{my.local.string} work as usual. Includes can also be used, with a path relative to the templates folder. Model attributes must be set on a new Map<String, Object> and can be accessed the usual way with ${myobj}. URLs need a special handling: the @{/myurl} syntax doesn’t work because the server address is unknown to Thymeleaf, so a "Model attribute" with the full URL must be used instead. The YadaWebUtil.getFullUrl() method exists for this purpose.

Example src\main\resources\template\email\bookVisit.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
                <meta charset="UTF-8"/>
                <th:block th:replace="/email/mailhead :: head" ></th:block>
   </head>
    <body>
            <th:block th:replace="/email/mailhead :: body" ></th:block>

        <h1>Booking confirmed</h1>
        <table>
                <tr><td>Day: </td><td th:with="dateFormat=#{date.format.long}" th:text="${#dates.format(slot.start, dateFormat)}">10 january</td></tr>
                <tr><td>Time: </td><td th:text="${slot.timeRange}">10:00 - 10:30</td></tr>
                <tr><td>People: </td><td>[[${totPeople}]]</td></tr>
        </table>

        <p>Thank you for joining us.</p>
        <p>If you need to cancel your booking, please <a th:href="@{${cancelLink}}">click here</a></p>

        <div th:replace="/email/mailfooter :: body" ></div>
    </body>
</html>

Email Subject

The subject of the email is localized and is defined in message.properties. The property name must have the format

email.subject.<templateName>

where <templateName> is the name of the template html file without extension. Example:

email.subject.bookVisit = Thank you for visiting {0}

Java Code

The YadaEmailService class is the low level service to send emails, both plain text and HTML, with attachments or inline images. An easier API is provided by the YadaEmailBuilder class.

public void confirmVisit(Booking booking, String customerEmail, File catalog, Locale locale) {

	String cancelLink = yadaWebUtil.getFullUrl("/booking/cancel/", locale, "bookingId", booking.getId());

	YadaEmailBuilder.instance("bookVisit", locale, yadaEmailService)
		.to(customerEmail)
		.from(config.getEmailFrom())
		.addModelAttribute("slot", booking.getSlot())
		.addModelAttribute("totPeople", booking.getTotPeople())
		.addModelAttribute("cancelLink", cancelLink)
		.subjectParams(booking.storeName())
		.addAttachment(pdf.getName(), catalog)
		.addInlineResources("logosmall", config.getEmailLogoImage())
		.send();
}

Internationalization

The HTML of the email template can contain localized text expressed via the usual thymeleaf #{} operator.

When you have emails with a lot of text, it may be more convenient to write the whole email in a specific language. Files for different languages other than the default one must have a _<lang> suffix. For example:

  • bookVisit.html

  • bookVisit_de.html

  • bookVisit_it.html