Wednesday, September 30, 2009

Sending email using Spring with JavaMail

Spring and JavaMail for sending emails:

Being a good java and spring developer, we might face a scenario sometime where we would be asked to construct and send an email from our application when something happens. This something may be like when our timesheet is pending or say when we have deposited or withdrawn some amount from our bank account. When we need to do that, there is nothing much simpler than using spring with javamail api for sending emails. Let us take the same example of the banking operation in our example and see how we configure spring with javamail to send emails.
As we all know, spring uses the concept of DI which is nothing but making our classes and interfaces as beans in the context files and wiring the properties directly or through references. Well, spring uses the same concept for emails. The 2 most important interfaces that we need to configure in spring is:
1. MailSender
2. MailMessage
MailSender: Spring comes with an email abstraction API that makes simple work of sending emails. This is MailSender interface. i.e. The purpose of MailSender interface is to send emails after configuring the mail properties from the MailMessage such as the from and to address, subject of the email, body of the email etc. Spring comes with 2 implementation of MailSender interface. They are CosMailSenderImpl and JavaMailSenderImpl. We will not talk about CosMailSenderImpl.
JavaMailSenderImpl is most versatile and widely used. It is a MailSender based on the JavaMail API. It allows us to send messages of MIME type and even to send non SMTP mail (such as Lotus Notes).
Here is how we configure the JavaMailSenderImpl as a bean in our context file, assuming that we would be sending the email to gmail ids, needing authentication

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="465" />
<property name="protocol" value="smtps" />
<property name="username" value="banking@gmail.com" />
<property name="password" value="banking" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtps.auth">true</prop>
<prop key="mail.smtps.starttls.enable">true</prop>
<prop key="mail.smtps.debug">true</prop>
</props>
</property>
</bean>

The properties explained in the mailSender are self explainatory. For ex: host specifies the hostname of the mail server that we will use for sending emails. port specifies that the mail server is listening to this port no. (This is by default 25. But smtp gmail listens on port no. 465). Since our mails server need authentication, we have specified the username and password property. We have also specified that authentication is required by specifying the mail.smtps.auth javaMailProperty to true. When we specify mail.smtps.starttls.enable as true, it means that the email is delivered in an encrypted way to the user, hence preventing from any unauthorized access.

MailMessage: MailMessage is nothing but the actual message that will be constructed while sending the email. We have lot of implementations of MailMessage but we will just look at its simplest implementation that sends emails as normal text and without any attachments etc. The simplest implementation of the MailMessage is SimpleMailMessage and as said earlier, we configure details like: from and to address, subject and body of the email using the mail message.
It is necessary to configure the MailMessage in the context file, but we have the option of setting its properties in the class level itself. However, it is a generic thing and we can thus create a template of a MailMessage in the context file by specifying the place holders in the template and replace those place holders in the actual class file. Let us see how we can do this:



<bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from">
<value>
<![CDATA[JDBCBanking <banking@gmail.com>]]>
</value>
</property>
<property name="subject">
<value><![CDATA[Amount deposited in your account></value>
</property>
<property name="text">
<value>
<![CDATA[Hello %NAME%!
This is to inform you that %AMOUNT% Rupees has been deposited to your account on %DAT%
Your balance is now Rupees %BAL%

Thanks
Admin-JDBCBanking
]]>
</value>
</property>
</bean>

Now, we need to wire the 2 beans that we created above (i.e. mailSender and mailMessage) into our service bean like:



<bean id="memberService" class="com.prokarma.service.MemberServiceImpl">
<property name=”mailSender” ref=”mailSender” />
<property name=”mailMessage” ref=”mailMessage” />
</bean>

Finally, lets see how we consider these properties in our class and replace the place holders for them with specific values and send email.

In MemberServiceImpl class, provide setter methods for MailSender and MailMessage as:


private MailSender mailSender;
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}

private SimpleMailMessage mailMessage;
public void setMailMessage(SimpleMailMessage mailMessage) {
this.mailMessage = mailMessage;
}

Here is how you can construct the mail message by obtaining from the context file and replacing the place holders and finally send it:



SimpleMailMessage message = new SimpleMailMessage(mailMessage);
message.setTo(member.getEmail().trim());

String text = message.getText(); //Obtains the text form the template
//replaces the %NAME% placeholder from template with actual member's name
text = StringUtils.replace(text,"%NAME%",member.getName());
text = StringUtils.replace(text,"%AMOUNT%",member.getDepositAmount().toString());
text = StringUtils.replace(text,"%DAT%",member.getDepositDate());
text = StringUtils.replace(text,"%BAL%",member.getBalance());

message.setText(text); // Finally, sets the message text with specific member details

mailSender.send(message);


We have first obtained the template text from the context file, then we edit it for a specific member by replacing the place holders with the specific member details and using StringUtils to replace them. Finally, we set the text of the message again and last step is to send the mail by calling mailSender.send(message);

No comments:

Post a Comment