Recently it was needed at my working place to have a module to send SMTP mails. I found out that Spring provides a nice wrapper around the Java Mail API so you do not need to deal with boilerplate code. Hence after a few hours of Googling and coding I was able to come up with an API which sends mail using Spring. Following I give you the code snippets required.
package com.test.commons.mailservices.core.remoting.ejb.service;
import com.test.commons.mailservices.core.exceptions.MailSenderException;
public interface MailSenderService {
/**
* This method sends the mail to multiple recipients with the given subject
* @param mailMsg The message needed to be send as plain text
* @param recipientAddresses The mail addresses in an array to which the mail has to be sent
* @param subject The subject of the mail to be sent
* @throws MailSenderException this exception wraps the MailException throw by the Spring framework
*/
public void sendMessage(String mailMsg,String[] recipientAddresses,String subject)throws MailSenderException;
/**
* This method sends the mail to a single recipient with the given subject
* @param mailMsg The message needed to be send as plain text
* @param recipientAddresses The mail addresses in an array to which the mail has to be sent
* @param subject The subject of the mail to be sent
* @throws MailSenderException this exception wraps the MailException throw by the Spring framework
*/
public void sendMessage(String mailMsg,String recipientAddress,String subject)throws MailSenderException;
/**
* This method sends the mail to multiple recipients which are given as comma separated values, with the given subject
* @param mailMsg The message needed to be send as plain text
* @param recipientAddresses The mail addresses in an array to which the mail has to be sent
* @param subject The subject of the mail to be sent
* @throws MailSenderException this exception wraps the MailException throw by the Spring framework
*/
public void sendMessageWithCommaSeparatedMailAddresses(String mailMsg,String recipientAddress,String subject)throws MailSenderException;
}
This is the main contract which any calling party can use to send mails. The method is overloaded so that clients can call with different functionality. Next I show you the implmentation of this interface as well as the exception class that i have defined which wraps the MailException thrown by Spring. I wrapped it so that any calling party only needs to know about the MailSending module and not about Spring exceptions.
package com.test.commons.mailservices.core.remoting.ejb.bl;
import org.apache.log4j.Logger;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import com.test.commons.mailservices.core.exceptions.MailSenderException;
import com.test.commons.mailservices.core.remoting.ejb.service.MailSenderService;
/**
* This is the Main class involved in sending email message to the outside world<br>
* The class uses the Spring Framework which wraps the java mail API to send mails.
* Common functionality of obtaining a SimpleMailMessage object is given by the parent<br>
* class named MailSenderCommon. The instance variables of the class are instantiated with<br>
* through a spring config. The spring config file responsible is mailconfig.spring.xml found <br>
* under the resources directory.
*
* @author dinuka
*
*/
public class MailSenderImpl extends MailSenderCommon implements MailSenderService {
private static final Logger log = Logger.getLogger(MailSenderImpl.class);
private MailSender mailSender;
private String fromAddress;
public MailSenderImpl() {
}
/**
* {@inheritDoc}
*/
public void sendMessage(String mailMsg, String[] recipientAddresses, String subject)throws MailSenderException {
if (mailMsg == null || recipientAddresses == null) {
log.error("Input parameters received for sendMessage(String,String[]) are null");
}
sendEmail(mailMsg, subject, recipientAddresses);
}
/**
* {@inheritDoc}
*/
public void sendMessage(String mailMsg, String recipientAddress, String subject)throws MailSenderException {
if (mailMsg == null || recipientAddress == null) {
log.error("Input parameters received for sendMessage(String,String) are null");
throw new IllegalArgumentException("Received Input Parameters Are Null");
}
sendEmail(mailMsg.trim(), subject, recipientAddress);
}
/**
* {@inheritDoc}
*/
public void sendMessageWithCommaSeparatedMailAddresses(String mailMsg, String recipientAddress, String subject)throws MailSenderException {
if (mailMsg == null || recipientAddress == null) {
log
.error("Input parameters received for sendMessageWithCommaSeparatedMailAddresses(String,String) are null");
throw new IllegalArgumentException("Received Input Parameters Are Null");
}
sendEmail(mailMsg, subject, recipientAddress.split(","));
}
public MailSender getMailSender() {
return mailSender;
}
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
public String getFromAddress() {
return fromAddress;
}
public void setFromAddress(String fromAddress) {
this.fromAddress = fromAddress;
}
private void sendEmail(String mailMsg, String subject, String... address)throws MailSenderException {
try {
mailSender.send(getSimpleMessage(mailMsg, fromAddress, subject, address));
} catch (MailException ex) {
log.error("MailSenderImpl: sendMessage() Exception occured" + ex.getMessage());
throw new MailSenderException(ex.getMessage());
}
}
}
package com.test.commons.mailservices.core.remoting.ejb.bl;
import java.util.Date;
import org.springframework.mail.SimpleMailMessage;
public class MailSenderCommon {
/**
* This is the common method which creates a simple message object which is used to send mails out
* Note that var arg is used as the second parameter to facilitate String[] and normal String object parsing
* to the same method. Also please note that you should always keep the var arg parameter as the last parameter in
* this method as the specification requires it.
* @param mailMsg
* @param addresses
* @return
*/
protected SimpleMailMessage getSimpleMessage(final String mailMsg, final String fromAddress,String subject,final String... addresses) {
SimpleMailMessage message = new SimpleMailMessage();
message.setSentDate(new Date());
message.setTo(addresses);
message.setFrom(fromAddress);
message.setSubject(subject);
message.setText(mailMsg);
return message;
}
}
package com.test.commons.mailservices.core.exceptions;
public class MailSenderException extends Exception{
/**
*
*/
private static final long serialVersionUID = -6281925344129197510L;
private String message;
public MailSenderException(String message){
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
Then we have the SMTP Authenticator class which is used for mail authentication. It is as follows;
package com.jkcs.commons.mailservices.core.remoting.ejb.bl;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
public class SmtpAuthenticator extends Authenticator {
private String username;
private String password;
public SmtpAuthenticator(String username, String password) {
super();
this.username = username;
this.password = password;
}
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
}
And finally you the following spring xml shows how to configure and integrate all this together.
<?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">
<!-- our Authenticator implementation -->
<bean id="smtpAuthenticator"
class="com.test.commons.mailservices.core.remoting.ejb.bl.SmtpAuthenticator">
<constructor-arg>
<value>${outgoing.mail.server.userid}</value>
</constructor-arg>
<constructor-arg>
<value>${outgoing.mail.server.password}</value>
</constructor-arg>
</bean>
<!-- now setup an authenticated session -->
<bean id="mailSession" class="javax.mail.Session"
factory-method="getInstance">
<constructor-arg>
<props>
<prop key="mail.smtp.auth">true</prop>
<!-- <prop key="mail.smtp.socketFactory.port">465</prop>
<prop key="mail.smtp.socketFactory.class">
javax.net.ssl.SSLSocketFactory
</prop>
<prop key="mail.smtp.socketFactory.fallback">
false
</prop> -->
</props>
</constructor-arg>
<constructor-arg ref="smtpAuthenticator" />
</bean>
<bean id="mailService" class="com.test.commons.mailservices.core.remoting.ejb.bl.MailSenderImpl">
<property name="mailSender" ref="mailSender"/>
<property name="fromAddress">
<value>${outgoing.mail.server.userid}</value>
</property>
</bean>
<!-- Mail service -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host">
<value>${outgoing.mail.server.ip}</value>
</property>
<property name="port">
<value>${outgoing.mail.server.port}</value>
</property>
<property name="username">
<value>${outgoing.mail.server.userid}</value>
</property>
<property name="password">
<value>${outgoing.mail.server.password}</value>
</property>
<property name="session" ref="mailSession" />
<property name="javaMailProperties">
<props>
<!-- Use SMTP-AUTH to authenticate to SMTP server -->
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.sendpartial">true</prop>
<!-- Use TLS to encrypt communication with SMTP server -->
<!-- <prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.sendpartial">true</prop> -->
</props>
</property>
</bean>
</beans>
As you can see i have used parameters as ${var_name}. This is because i have used Spring property file loading mechanism. Hence those variables are taken from a .property file. To configure that use the following;
<bean id="PropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!--
The order of these properties files is important, as properties
will override one another
-->
<value>xxx.properties</value>
<value>mail.properties</value>
</list>
</property>
</bean>
Thats about it. Hope this would be helpful to someone who is looking to do the same.