Sending email notifications from enterprise application is very common scenario. I know several methods to solve this puzzle, below you can find short summary.
To send an email from the application at least SMTP server address must be configured.
Because released application binary (e.g: WAR file) should be portable across environments (integration, QA, staging,
production) configuration must be externalized.
Below I present code snippets to configure SMTP server address as JNDI entry.
Sample JNDI entry for JBoss:
1 2 3 4 5 6 7 8 9 10 11 12
Sample JNDI entry for Tomcat:
1 2 3 4 5 6 7
When mail session is configured as JNDI resource, it can be easily utilized by Spring Framework mail sender:
1 2 3 4 5
Now it is time for more tough part, how to use mail sender correctly? There are at least four options, choose the best one for you:
- Direct (Sync) Use mail session directly from the application service in the web request thread.
- Direct (Async) Use mail session directly from the application service using
- Database Queue Save messages into database table and create cron job to send the emails periodically.
- JMS Queue Put messages into JMS queue and attach JMS listener to process and send emails.
I collected a few non-functional and functional common requirements together with short categorization for each method.
|Direct (Sync)||Direct (Async)||Database Queue||JMS Queue|
|Application works even if the SMTP is down||no||no||yes||yes|
|Web request thread is not blocked||no||yes||yes||yes|
|Mail aggregation, scheduled sending, etc.||no||no||yes||limited|
|Control over SMTP requests throttle||no||limited||limited||yes|
|Redelivery policy, do not lost messages if SMTP is down||no||no||limited||yes|
I would start with “Database Queue” approach, at least if JMS is not already used in the project or you do not have to send thousands of emails. “Direct” method is not an option at all IMHO.
Separate part of the subject is to how to create email body. In most situation I used some template engine, like Freemarker or Thymeleaf. The template can be defined as internal WAR resource or can be loaded from database if the template needs to be adjusted on runtime.