1)Introduction
The Spring Framework provides a supportive utility library for sending email that shields the user from the essentials of the core mailing system and is dependable for low level resource handling on behalf of the customer. Spring Framework uses the following package as a root level package for the email support: org.springframework.mail MailSender is the essential interface for sending emails. Spring facilitates sending of email through the MailSender interface, offering two different implementations – one based on JavaMail, and one using Jason Hunter’s MailMessage class. If you are beginner for spring framework, please read our article on introduction to spring framework, spring aop, spring mvc and list of spring articles. Javabeat covers extensive articles on the spring framework. If you are interested in receiving the updates, please subscribe here.
also read:
The complete MailSender interface is shown here:
public interface MailSender { void send(SimpleMailMessage simpleMessage) throws MailException; void send(SimpleMailMessage[] simpleMessages) throws MailException; }
SimpleMailMessage is a JavaBean that holds what should be sent and to whom. This allows for sending mail messages using the default mail message properties such as from, to, cc, bcc, subject, and text. For more complicated email messages, the two implementations provide support for MIME messages.
2)Working with Email Functionality
To start with this concept let us consider a simple example of wiring up a mail in a Spring application:
<bean id="mailSender" class= "org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host"><value>mail.myexample.com</value></property> </bean>
The above bean definition enables you to send an email from anywhere in your application. Application code that would send an email using this mail sender would look like the following:
Sample Code:
package com.myexample.mail.base; public interface Registration { void register(UserRegistration userRegistration); }
Implementation for the above interface looks like the follwoing:
Sample Code:
package com.myexample.mail.impl; import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.MailException; public class RegistrationImpl implements Registration{ private MailSender mailSender; private SimpleMailMessage messageTemplate; public void setMailSender(MailSender mailSender){ this.mailSender = mailSender; } public void setMessageTemplate(SimpleMailMessage messageTemplate) { this. messageTemplate = messageTemplate; } public void register(UserRegistration userRegistration) { //do all the business logic in here //Create a thread safe copy of the template message and customize it SimpleMailMessage message = new SimpleMailMessage(this. messageTemplate); message.setFrom(userRegistration.getUser().getFromEmailAddress()); message.setTo(userRegistration.getUser().getToEmailAddress()); message.setText("Hi" + userRegistration.getUser().getFirstName + userRegistration.getUser().getLastName + ", Welcome, This is your user registration confirmation."); try { mailSender.send(message); }catch(MailException exception){ //log the message and go on… System.err.println(exception.getMessage()); } } }
The above code tells you that, how to send a simple mail message using the mail sender defined in the application context. To plug in the mail sender to the business logic, you will simply use Dependency Injection, shown below:
<bean id="messageTemplate"subject" value="Registration Confirmation"/> </bean> <bean id="registration" > <property name="mailSender"><ref bean="mailSender"></property> <property name=" messageTemplate"><ref bean=" messageTemplate"></property> </bean>
3)Reusing an Existing Mail Session
Although it is very useful while testing or running outside of a container, specifying the mail sending details in the application context can be nuisance because the host and other properties may change on deployment. When running an application inside a container that already provides a mail session, the reuse of that session is preferred. Consider, for instance, running inside a container that exposes a JavaMail session through JNDI under the JNDI name java:/Mail. In this case the bean definition for the mail sender looks like this:
<bean id="mailSender" > <property name="session"><ref bean="mailSession"></property> </bean> <bean id="mailSession" > <property name="jndiName"><value>java:/Mail</value></property> </bean>
The following fragment of code shows how we can make use of the above bean definitions:
Sample Code:
import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSenderImpl; public class CreateUserImpl implements CreateUser { /** * This field holds SimpleMailMessage Object */ private SimpleMailMessage simpleMailMessage; public void setSimpleMailMessage(SimpleMailMessage simpleMailMessage) { this. simpleMailMessage = simpleMailMessage; } public void sendEmailToEmployee(String password, String toMail, String mailServerHost, String fromAddress) { JavaMailSenderImpl mailHost = new JavaMailSenderImpl(); SimpleMailMessage msg = new SimpleMailMessage(this.simpleMailMessage); mailHost.setHost(mailServerHost); msg.setTo(toMail.trim()); msg.setFrom(fromAddress); ResourceBundle myResources = ResourceBundle.getBundle("mailmessage", Locale.US); HashMap dataHash = new HashMap(); dataHash.put("password", password); MailParser mp = new MailParser(); String result = mp.parse(myResources.getString("password.apps.txt"), dataHash); msg.setSubject(myResources.getString("password.apps.sub")); msg.setText(result); mailHost.send(msg); } }
From the above bean definitions, the JndiObjecFactoryBean is used to look up the mail session through JNDI. The retrieved mail session is set as the session in the mail sender. This approach enables the reuse of one mail session for all application running in the container and therefore allows for a single point of configuration of the mail session.
4)Generic Mail Manager
The mail manager will use Velocity templates to allow for flexible electronic mail functionality. You can get more information at http://jakarta.apache.org/velocity. Velocity is a popular choice for generating mail messages, as it can incorporate variables in its templates.
It is purely a HTML-based template, and it is plain text it can be created using any kind of your favorite editor without choice to having to be familiar with Java. The following sample shows how we can create a velocity template:
Dear ${customerFirstName}: #if($username && $username != "") Your private login name is ${username} #end In just a couple of days, we'll be sending you an email outlining all the benefits that come with ${APPLICATIONNAME} membership. Tools you can start using right away to save, plan and make every trip better. We look forward to serving you! Sincerely, ${EMAILSIGNATURELINE}
We start by defining a MailManager interface, which defines the business methods needed for a mail manager. The main value add here over Spring’s MailSender interface – which of course is used under the covers – is Velocity-based mail templating support:
Sample Code:
package com.myexample.mail.base; public interface MailManager { void sendMail(String senderName, String senderAddress, Map from, Map to, Map cc, Map bcc, String subject, Map mergeObjects, String template) throws MailException; void sendMail(Map to, List objects, String template) throws MailException; }
Notice that each argument denoting a type of recipient is in the form of a Map. This is to allow the user to send an electronic mail message with multiple recipients for each recipient type, while specifying a full name for the recipient alongside the email address. Also note the convenience method to send a message while specifying only the “to” recipient.
The next step is to create a default implementation for our generic mail manager. We start out by setting up the skeleton for the default implementation:
Sample Code:
package com.myexample.mail.impl; import org.apache.velocity.app.VelocityEngine; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessagePreparator; import org.springframework.ui.velocity.VelocityEngineUtils; public class MailManagerImpl implements MailManager { private JavaMailSender javaMailSender; private Resource templateBase; private VelocityEngine velocityEngine; private String defaultFromName; private String defaultFromAddress; private String textTemplateSuffix = "textTemplate.vm"; private String htmlTemplateSuffix = "htmlTemplate.vm"; private String overrideToAddress; // setters (and optionally getters) for all private instance fields public void sendMail(Map to, List objects, String template) throws MailException { sendMail(null, to, null, null, objects, template); } public void sendMail(String senderName, String senderAddress, Map to, Map cc, Map bcc, String subject, Map mergeObjects, templateLocation) throws MailException { // implementation of the functionality goes here } }
Bean definition for the above class will look like this:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="javaMailSender"> <property name="host" value="mail.mycompany.com"/> </bean> <bean id="mailManager"> <property name=" javaMailSender" ref=" javaMailSender"/> <property name="velocityEngine" ref="velocityEngine"/> </bean> <bean id="velocityEngine"> <property name="velocityProperties"><value>.loader=class class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoadervalue> </property> <</bean> </beans>
5)Creating the mail message
After setting up the skeleton for the implementation of the generic mail manager, now its time to generate a mail message. The Spring Framework provides a helper class for easy implementation of a MIME message. So the first part of the sendMail method implementation creates a mail message using the mail sender and uses that message to create a helper for it.
Sample Code:
//create a MIME message using the mail sender implementation MimeMessage message = javaMailSender.createMimeMessage(); //create the message using the specified template MimeMessageHelper helper; try{ helper = new MimeMessageHelper(message, true, "UTF-8"); }catch(MessageException exception) { Throw new MailPreparationException("Couble not able to create a MIME message", exception); }
6)Recipient Handling
Now, the handling of the recipient must be implemented. A fundamental implementation looks like the following:
Sample Code:
//add the 'from' and the sender to the message helper.setFrom(senderAddress. senderName); //add the 'cc' if(cc !=null && !cc.isEmpty()) { Iterator itr = cc.keySet().iterator(); while(itr.hasNext()) { String name = (String) itr.next(); String recipient = (String) cc.get(name); if(overrideToAddress !=null) { Recipient = defaultToAddress; } helper.addCc(recipient, name); } } //add the 'bcc' if(bcc !=null && !bcc.isEmpty()) { Iterator itr = bcc.keySet().iterator(); while(itr.hasNext()) { String name = (String) itr.next(); String recipient = (String) bcc.get(name); if(overrideToAddress !=null) { Recipient = defaultToAddress; } helper.addBcc(recipient, name); } } //add the 'to' if(to !=null && !to.isEmpty()) { Iterator itr = to.keySet().iterator(); while(itr.hasNext()) { String name = (String) itr.next(); String recipient = (String) to.get(name); if(overrideToAddress !=null) { Recipient = defaultToAddress; } helper.addTo(recipient, name); } }else { //use the default 'to' if(defaultToAddress != null) { helper.addTo(defaultToAddress, name); }else { helper.addTo(toAddress, toName); } }
7)Setting the Content
The next step is to set the content of the mail message. We use Velocity to combine the list of objects into the particular template. The consequence is set as the content of the message.
Sample Code:
StringWriter writer = new StringWriter(); VelocityEngineUtils.mergetTemplate(velocityEngine, templateLocation + "/" + htmlTemplateSuffix, mergeObjects, writer); String htmlString = new StringWriter(); VelocityEngineUtils.mergetTemplate(velocityEngine, templateLocation + "/" + htmlTemplateSuffix, mergeObjects, writer); writer.close(); htmlString.close(); helper.setText(writer.toString(), htmlString.toString()); helper.setSubject(subject);
Note the use of a foundation source for our implementation of the message helper. Depending on the application deployment environment, different resources can be selected for retrieving the Velocity templates. Velocity provides the resources to cache the templates and handles modifications to the templates to be integrated without the need to concern oneself with the information.
Here the question arises from you asking that, is it possible for you to attach any files while sending the mails?
Let us develop our MailManager by allowing more files in a directory relative to the template directory to be added as attachments for the message. The added attachments are given the file name as the ID for referencing the attachment from the message content. The following fragment of code shows you the implementation of this functionality:
//retrieve contents of the attachments File attachmentFile = templateBase.createRelative("mail/" + template + "/attachment").getFile(); File[] attachmentArray = attachmentFile.listFiles(); if(attachmentArray != null) { for(int i = 0; i < attachmentArray.length; i++) { //add the attachment to the message helper helper.addAttachment(attachmentArray[i].getName(), new FileDataSource(attachmentArray[i])); } } //retrieve contents of the attachments File inlineFile = templateBase.createRelative("mail/" + template + "/inline").getFile(); File[] inlinesArray = inlineFile.listFiles(); if(inlinesArray != null) { for(int i = 0; i < inlinesArray.length; i++) { //add the attachment to the message helper helper.addAttachment(inlinesArray [i].getName(), new FileDataSource(inlinesArray [i])); } }
8)Sending the mail message
After we create the message, setting its contents, recipients are handled and all the attachments are added, the message is ready to be sent. Using the MailSender wired up to the mail manager implementation, sending the message is easy. Just call the send() method with the created and configured mail message as the argument.
mailSender.send(message);
9)Conclusion
This is to conclude that we have created a sample of generic mail manager by means of the mail functionality provided by the Spring Framework. The developed mail manager can be plugged in the application context of any application to add email as an option to communicate with your customers.
also read:
If you have any questions on the spring framework integration with email, please post it in the comments section. Also search in our website to find lot of other interesting articles related to the spring framework. There are some interesting articles about spring framework, interview questions, spring and hibernate integration,etc.
If you would like to receive the future java articles from our website, please subscribe here.