JavaBlog.fr / Java.lu DEVELOPMENT,Java,Spring Java/Spring: Send email in your applications

Java/Spring: Send email in your applications

Hello,

After my post about the Fake SMTP Server/SMTP4DEV, today, I would present a solution for the sending of email in your java applications.
So, we will consider sending emails using the Spring framework.
Indeed, Spring provides a number of utility classes that facilitate the integration of your applications with the JavaMail API, especially the classes org.springframework.mail.javamail.JavaMailSenderImpl and org.springframework.mail.javamail.MimeMessageHelper.

To use Spring to integrate JavaMail in your applications, we have obviously the jars spring-2.5.5.jar, mail-1.3.2.jar, junit-4.1.jar, commons-beanutils-1.6.jar, commons-io-1.4.jar, commons-logging-1.1.1.jar.
To check the mail sent by our solution, we will use Fake SMTP Server or the SMTP4DEV software as descried here.

Important note: Some classes in the mail-1.3.2.jar exist also in the library geronimo-javamail_1.4_spec-1.3.jar, so, in order to avoid the conflict, remove the geronimo-javamail library from your project using this solution based on mail-1.3.2.jar.

Configuration
The mail sending is implemented in a main static class named MailSender with the support of message content through a configuration templates. This class is configured in Spring context file spring-mail-config.xml:

01<?xml version="1.0" encoding="UTF-8"?>
02<beans ...>
03    <!--
04     | Factory bean created in order to use a unique instance of "MailSender" in:
05     | + MailSender mailSender = (MailSender) ctx.getBean("mailSender");
06     | OR
07     | + MailSender.getInstance().sendMail(emails, templateName, mappingData);
08     -->
09    <bean id="mailSenderFactoryBean" class="com.ho.test.mail.ex1.sending.MailSenderFactoryBean"/>
10 
11    <!--
12     | This bean is used to:
13     | + build the message from template;
14     | + mapping datas to the template;
15     | + send email;
16     -->
17    <bean id="mailSender" class="com.ho.test.mail.ex1.sending.MailSender"
18        factory-bean="mailSenderFactoryBean"
19        factory-method="createInstance">
20    </bean>      
21</beans>

… this Spring context will be accessible via the singleton CommonContext:

01public class CommonContext {
02    private static CommonContext currentInstance = null;
03     
04    /** The ctx. */
05    private ApplicationContext ctx;
06 
07    private CommonContext() {
08        //load spring bean
09        ctx = new ClassPathXmlApplicationContext(new String[] {"spring-mail-config.xml"});
10    }
11     
12    public static synchronized CommonContext getInstance() {
13        if (currentInstance == null) {
14            currentInstance = new CommonContext();
15        }
16        return currentInstance;
17    }
18 
19    public ApplicationContext getCtx() {
20        return ctx;
21    }
22 
23    public void setCtx(ApplicationContext ctx) {
24        this.ctx = ctx;
25    }
26}

…so, the Spring context contains a factory bean named MailSenderFactoryBean needed only in order to use an unique instance of the MailSender in:

1MailSender mailSender = (MailSender) ctx.getBean("mailSender");
2//OR
3MailSender.getInstance().sendMail(emails, templateName, mappingData);
1public class MailSenderFactoryBean{
2    public MailSender createInstance() throws Exception {
3        MailSender mailSender = MailSender.getInstance();
4        return mailSender;
5    }
6}

…., here, a part of the main class MailSender which allows:

  • the mail sending with the loading of mail session via the class MailSessionLoader,
  • the formating of message due to an internal class TemplateMailBean building the message from template and its corresponding datas in the ${parameterName} format,
01public class MailSender {
02 
03    private static MailSender singleton = null;
04    private MailSender() {}
05    public static synchronized MailSender getInstance() {
06        if (singleton == null){
07            singleton = new MailSender();          
08        }
09        return singleton;
10    }
11     
12     
13    @SuppressWarnings("unchecked")
14    public synchronized void sendMail(String smtpMailFrom, String[] recipientsEmailTo, String[] recipientsEmailCc, String[] recipientsEmailBcc, String templateName, Map<String, String> mappingData, Map<String, InputStreamSource> attachments) throws Throwable{
15        System.out.println("sendMail()");
16         
17        // MAIL SESSION
18        /*javax.mail.Session mailSession = null;
19        {
20            Hashtable<String,String> env = new Hashtable<String,String> ();
21            env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
22            mailSession = (javax.mail.Session) new InitialContext(env).lookup("java:comp/env/mail/Session");
23        }*/
24        //
25        MailSessionLoader loader=new MailSessionLoader();
26        Session mailSession=loader.loadJavaMailSession();
27             
28        // Build the message
29        MimeMessage mailMsg = new MimeMessage(mailSession);
30        MimeMessageHelper helper = new MimeMessageHelper(mailMsg, true);
31        // Set the mail sender
32        {
33            if(smtpMailFrom == null){
34                smtpMailFrom = SMTPConstant.SMTP_SENDER_EMAIL;
35            }
36            helper.setFrom(new InternetAddress(smtpMailFrom));
37        } // end-block
38 
39        // Set the recipient To
40        {
41            if(recipientsEmailTo!=null){
42                for (int i = 0; i < recipientsEmailTo.length; i++) {
43                    if(recipientsEmailTo[i]!=null && !"".equalsIgnoreCase(recipientsEmailTo[i].trim())){
44                        helper.addTo(new InternetAddress(recipientsEmailTo[i].trim()));
45                    }
46                }
47            }
48        } // end-block
49 
50        ....
51 
52         
53        TemplateMailBean bean=null;
54        {
55            bean = new TemplateMailBean(templateName, mappingData);
56        }
57                 
58        ....           
59         
60    }
61...
62}

…this bean TemplateMailBean uses the templates configured in constants of the class SMTPConstant:
TEMPLATE_MAIL_GENERIC
subject=${subject}
body=${htmlBody}
footer=${footer}

TEMPLATE_MAIL_SPECIFIC
subject=JAVABLOG: Error for post ${referencePOST}
body=An error is occured during the treatment of system with the following message: ${htmlMessage}
footer=This is an automatically generated e-mail sent by JAVABLOG, please don’t reply.

Simple Example
Below, a simple example of mail sending using the generic template TEMPLATE_MAIL_GENERIC:

01// TemplateName
02String templateName = "TEMPLATE_MAIL_GENERIC";
03             
04// Recepients To
05String[] recipientsEmailTo = new String[]{"huseyin.ozveren@javablog.fr", "ozveren@java.lu"};
06 
07// Data to be used
08Map<String, String> mappingData = new HashMap<String, String>();
09mappingData.put("subject","JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547");
10mappingData.put("htmlBody"," - Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR");
11mappingData.put("footer","- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.");
12//
13MailSender.getInstance().sendMail(recipientsEmailTo, templateName, mappingData);

… traces in the output would be:

1sendMail()
2MailSessionLoader.loadJavaMailSession()
3templateName=TEMPLATE_MAIL_GENERIC - mappingData={footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply., subject=JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547, htmlBody= - Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR}
4prop {body=- Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR, subject=JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547, footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.}
5INFO : MAILSENT : Sat Aug 11 01:28:55 CEST 2012 : MailSender : subject : JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547 recipients : huseyin.ozveren@javablog.fr;ozveren@java.lu;

Advanced Tests
The project in attachement contains a JUNIT TestMailSender with two concrets cases:

  • an example of mail sending using the generic template TEMPLATE_MAIL_SPECIFIC containing the parameters referencePOST and htmlMessage:
    01// TemplateName
    02String templateName = "TEMPLATE_MAIL_SPECIFIC";
    03 
    04// Recepients To
    05String[] recipientsEmailTo = new String[]{"huseyin.ozveren@javablog.fr", "ozveren@java.lu"};
    06             
    07// Data to be used
    08Map<String, String> mappingData = new HashMap<String, String>();
    09mappingData.put("referencePOST", "123456");
    10mappingData.put("htmlMessage", "..... message error...... ");
    11 
    12MailSender.getInstance().sendMail(recipientsEmailTo, templateName, mappingData);

    … traces in the output would be:

    1sendMail()
    2MailSessionLoader.loadJavaMailSession()
    3templateName=TEMPLATE_MAIL_SPECIFIC - mappingData={htmlMessage=..... message error...... , referencePOST=123456}
    4prop {body=An error is occured during the treatment of system with the following message: ..... message error...... , subject=JAVABLOG: Error for post 123456, footer=This is an automatically generated e-mail sent by JAVABLOG, please don't reply.}
    5INFO : MAILSENT : Sat Aug 11 01:28:56 CEST 2012 : MailSender : subject : JAVABLOG: Error for post 123456 recipients : huseyin.ozveren@javablog.fr;ozveren@java.lu;

  • an example of mail sending using the generic template TEMPLATE_MAIL_GENERIC, with recepients in To, CC and with 2 text files in attachement:
    01// TemplateName
    02String templateName = "TEMPLATE_MAIL_GENERIC";
    03             
    04// From
    05String smtpMailFrom = "contact@java.lu";
    06 
    07// Recepients To
    08String[] recipientsEmailTo = new String[]{"huseyin.ozveren@javablog.fr", "ozveren@java.lu"};
    09 
    10// Recepients Cc
    11String[] recipientsEmailCc =  new String[]{"huseyinCC@javablog.fr", "ozverenCC@java.lu"};
    12             
    13// Data to be used
    14Map<String, String> mappingData = new HashMap<String, String>();
    15mappingData.put("subject","JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547");
    16mappingData.put("htmlBody"," - Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR");
    17mappingData.put("footer","- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.");
    18 
    19// Attachments
    20Map<String, InputStreamSource> attachments = new HashMap<String, InputStreamSource>();
    21{
    22    // Creation of a file1
    23    {
    24        File attachmentFile1 = null;
    25        attachmentFile1 = File.createTempFile("attachment1", ".txt");
    26        attachmentFile1.deleteOnExit();
    27        FileOutputStream flout = new FileOutputStream(attachmentFile1);
    28        flout.write("text JAVABLOG.FR JAVA.LU text ".getBytes("UTF-8"));
    29        flout.close();
    30        InputStreamSource iss1 = null;
    31        iss1 = new InputStreamResource(new FileInputStream(attachmentFile1));
    32        attachments.put("MyAttachment1.txt", iss1);
    33    }
    34    // Creation of a file2
    35    {
    36        File attachmentFile2 = null;
    37        attachmentFile2 = File.createTempFile("attachment2", ".txt");
    38        attachmentFile2.deleteOnExit();
    39        FileOutputStream flout = new FileOutputStream(attachmentFile2);
    40        flout.write("text JAVABLOG.FR JAVA.LU text ".getBytes("UTF-8"));
    41        flout.close();
    42        InputStreamSource iss2 = null;
    43        iss2 = new InputStreamResource(new FileInputStream(attachmentFile2));
    44        attachments.put("MyAttachment2.txt", iss2);
    45    }
    46}
    47 
    48MailSender.getInstance().sendMail(smtpMailFrom, recipientsEmailTo, recipientsEmailCc, null, templateName, mappingData, attachments);

    … traces in the output would be:

    1sendMail()
    2MailSessionLoader.loadJavaMailSession()
    3templateName=TEMPLATE_MAIL_GENERIC - mappingData={footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply., subject=JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547, htmlBody= - Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR}
    4prop {body=- Generic - An error is occured during the treatment of system with the following message:<br/> <a href='http://www.javablog.fr'>clic here</a> to access to JAVABLOG.FR, subject=JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547, footer=- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.}
    5INFO : MAILSENT : Sat Aug 11 01:28:56 CEST 2012 : MailSender : subject : JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547 recipients : huseyin.ozveren@javablog.fr;ozveren@java.lu;huseyinCC@javablog.fr;ozverenCC@java.lu;

For more informations, you could contact me.

Download: test_mail1.zip

Best regards,

Huseyin OZVEREN

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Related Post