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:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <!-- 
     | Factory bean created in order to use a unique instance of "MailSender" in:
     | + MailSender mailSender = (MailSender) ctx.getBean("mailSender");
     | OR
     | + MailSender.getInstance().sendMail(emails, templateName, mappingData);
     --> 
	<bean id="mailSenderFactoryBean" class="com.ho.test.mail.ex1.sending.MailSenderFactoryBean"/>

    <!-- 
     | This bean is used to:
     | + build the message from template; 
     | + mapping datas to the template;
     | + send email;
     -->
	<bean id="mailSender" class="com.ho.test.mail.ex1.sending.MailSender" 
		factory-bean="mailSenderFactoryBean" 
		factory-method="createInstance">
	</bean>    	
</beans>

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

public class CommonContext {
	private static CommonContext currentInstance = null;
	
	/** The ctx. */
	private ApplicationContext ctx;

	private CommonContext() {
		//load spring bean
		ctx = new ClassPathXmlApplicationContext(new String[] {"spring-mail-config.xml"});
	}
	
	public static synchronized CommonContext getInstance() {
		if (currentInstance == null) {
			currentInstance = new CommonContext();
		}
		return currentInstance;
	}

	public ApplicationContext getCtx() {
		return ctx;
	}

	public void setCtx(ApplicationContext ctx) {
		this.ctx = ctx;
	}
}

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

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

…., 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,
public class MailSender {

 	private static MailSender singleton = null;
	private MailSender() {}
	public static synchronized MailSender getInstance() {
		if (singleton == null){
			singleton = new MailSender();			
		}
		return singleton;
	}
	
	
	@SuppressWarnings("unchecked")
	public synchronized void sendMail(String smtpMailFrom, String[] recipientsEmailTo, String[] recipientsEmailCc, String[] recipientsEmailBcc, String templateName, Map<String, String> mappingData, Map<String, InputStreamSource> attachments) throws Throwable{
		System.out.println("sendMail()");
		
		// MAIL SESSION
		/*javax.mail.Session mailSession = null;
		{
			Hashtable<String,String> env = new Hashtable<String,String> (); 
			env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
			mailSession = (javax.mail.Session) new InitialContext(env).lookup("java:comp/env/mail/Session");
		}*/
		//
		MailSessionLoader loader=new MailSessionLoader();
		Session mailSession=loader.loadJavaMailSession();
			
		// Build the message
		MimeMessage mailMsg = new MimeMessage(mailSession);
		MimeMessageHelper helper = new MimeMessageHelper(mailMsg, true);
		// Set the mail sender
		{
			if(smtpMailFrom == null){
				smtpMailFrom = SMTPConstant.SMTP_SENDER_EMAIL;
			}
			helper.setFrom(new InternetAddress(smtpMailFrom));
		} // end-block

		// Set the recipient To
		{
			if(recipientsEmailTo!=null){
				for (int i = 0; i < recipientsEmailTo.length; i++) {
					if(recipientsEmailTo[i]!=null && !"".equalsIgnoreCase(recipientsEmailTo[i].trim())){
						helper.addTo(new InternetAddress(recipientsEmailTo[i].trim()));
					}
				}
			}
		} // end-block

		....

		
		TemplateMailBean bean=null;
		{
			bean = new TemplateMailBean(templateName, mappingData);
		}
				
		....			
		
	}
...
}

…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:

// TemplateName
String templateName = "TEMPLATE_MAIL_GENERIC";
			
// Recepients To
String[] recipientsEmailTo = new String[]{"huseyin.ozveren@javablog.fr", "ozveren@java.lu"};

// Data to be used
Map<String, String> mappingData = new HashMap<String, String>();
mappingData.put("subject","JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547");
mappingData.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");
mappingData.put("footer","- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.");
//
MailSender.getInstance().sendMail(recipientsEmailTo, templateName, mappingData);

… traces in the output would be:

sendMail()
MailSessionLoader.loadJavaMailSession()
templateName=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}
prop {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.}
INFO : 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:
    // TemplateName
    String templateName = "TEMPLATE_MAIL_SPECIFIC";
    
    // Recepients To
    String[] recipientsEmailTo = new String[]{"huseyin.ozveren@javablog.fr", "ozveren@java.lu"};
    			
    // Data to be used
    Map<String, String> mappingData = new HashMap<String, String>();
    mappingData.put("referencePOST", "123456");
    mappingData.put("htmlMessage", "..... message error...... ");
    
    MailSender.getInstance().sendMail(recipientsEmailTo, templateName, mappingData);
    

    … traces in the output would be:

    sendMail()
    MailSessionLoader.loadJavaMailSession()
    templateName=TEMPLATE_MAIL_SPECIFIC - mappingData={htmlMessage=..... message error...... , referencePOST=123456}
    prop {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.}
    INFO : 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:
    // TemplateName
    String templateName = "TEMPLATE_MAIL_GENERIC";
    			
    // From
    String smtpMailFrom = "contact@java.lu";
    
    // Recepients To
    String[] recipientsEmailTo = new String[]{"huseyin.ozveren@javablog.fr", "ozveren@java.lu"};
    
    // Recepients Cc
    String[] recipientsEmailCc =  new String[]{"huseyinCC@javablog.fr", "ozverenCC@java.lu"};
    			
    // Data to be used
    Map<String, String> mappingData = new HashMap<String, String>();
    mappingData.put("subject","JavaBlog.fr: - Generic -  Error Notification for the post 123465798012546547");
    mappingData.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");
    mappingData.put("footer","- Generic - This is an automatically generated e-mail sent by JAVABLOG, please don't reply.");
    
    // Attachments
    Map<String, InputStreamSource> attachments = new HashMap<String, InputStreamSource>();
    {
    	// Creation of a file1
    	{
    		File attachmentFile1 = null;
    		attachmentFile1 = File.createTempFile("attachment1", ".txt");
    		attachmentFile1.deleteOnExit();
    		FileOutputStream flout = new FileOutputStream(attachmentFile1);
    		flout.write("text JAVABLOG.FR JAVA.LU text ".getBytes("UTF-8"));
    		flout.close();
    		InputStreamSource iss1 = null;
    		iss1 = new InputStreamResource(new FileInputStream(attachmentFile1)); 
    		attachments.put("MyAttachment1.txt", iss1);
    	}
    	// Creation of a file2
    	{
    		File attachmentFile2 = null;
    		attachmentFile2 = File.createTempFile("attachment2", ".txt");
    		attachmentFile2.deleteOnExit();
    		FileOutputStream flout = new FileOutputStream(attachmentFile2);
    		flout.write("text JAVABLOG.FR JAVA.LU text ".getBytes("UTF-8"));
    		flout.close();
    		InputStreamSource iss2 = null;
    		iss2 = new InputStreamResource(new FileInputStream(attachmentFile2)); 
    		attachments.put("MyAttachment2.txt", iss2);
    	}
    }
    
    MailSender.getInstance().sendMail(smtpMailFrom, recipientsEmailTo, recipientsEmailCc, null, templateName, mappingData, attachments); 
    

    … traces in the output would be:

    sendMail()
    MailSessionLoader.loadJavaMailSession()
    templateName=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}
    prop {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.}
    INFO : 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