Email sending with Spring Batch - codecentric AG Blog

:

Like in the last post (Send data secure with sftp and Spring Batch) this post is handling a not very new but also very important technology. It shows, how sending emails can be handled easily with Spring Batch. This framework has some ready components, which only must be combined.

In the following example three beans are declared, which are needed for sending emails:

  • The JavaMail Bean and set all needed parameters
  • The Tasklet Bean, which calls the service for sending the mail. This bean is the central bean and reference both other beans.
  • The Service bean

The Java Mail Bean

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="smtp.yourEmailDomain.de"/>
    <property name="port" value="25"/>
    <property name="username" value="yourUserName"/>
    <property name="password" value="yourPassword"/>
    <property name="javaMailProperties">
        <props>
            <prop key="mail.smtp.auth">true</prop>
        </props>
    </property>
</bean>

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.yourEmailDomain.de"/> <property name="port" value="25"/> <property name="username" value="yourUserName"/> <property name="password" value="yourPassword"/> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> </props> </property> </bean>

The Tasklet Bean

<bean id="sendMailManager">
    <property name="mailSender" ref="mailSender"/>
    <property name="sendMailService" ref="sendMailService"/>
    <property name="senderAddress" value="sender@emailaddress.de"/>
    <property name="recipient" value="recipient@emailaddress.de"/>
    <property name="attachmentFilePath" value="/path/to/attachment/file/"/>
</bean>

<bean id="sendMailManager"> <property name="mailSender" ref="mailSender"/> <property name="sendMailService" ref="sendMailService"/> <property name="senderAddress" value="sender@emailaddress.de"/> <property name="recipient" value="recipient@emailaddress.de"/> <property name="attachmentFilePath" value="/path/to/attachment/file/"/> </bean>

The Service Bean

<bean id="sendMailService" class="de.batch.mail.SendMailService" />

<bean id="sendMailService" class="de.batch.mail.SendMailService" />

Now these three beans can be called by a BatchJob.

<batch:job id="sendMailJob" restartable="false">
  <batch:step id="sendMailStep">
    <batch:tasklet ref="sendMailManager" />
  </batch:step>
</batch:job>

<batch:job id="sendMailJob" restartable="false"> <batch:step id="sendMailStep"> <batch:tasklet ref="sendMailManager" /> </batch:step> </batch:job>

Now you have to create the needed Java class files wich are called by the beans in XML. The Bean “sendMailService” is a reference to the de.batch.mail.SendMailService class. In the BatchJob it is called by the Tasklet named “sendMailManager”.

 
package de.batch.mail;
 
import java.io.File;
import javax.ejb.Stateless;
import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.annotations.Name;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
 
@Stateless
@Name("SendMail")
public class SendMailService {
 
    private static final Log log = LogFactory.getLog(SendMailService.class);
    private JavaMailSender mailSender;
    private String senderAddress;
    private String recipient;
    private String attachmentFilePath;
 
    // set the fields
    public void setFields(JavaMailSender mailSender, String senderAddress, String recipient, String attachmentFilePath) {
 
        this.mailSender = mailSender;
        this.senderAddress = senderAddress;
        this.recipient = recipient;
        this.attachmentFilePath = attachmentFilePath;
    }
 
    public void sendMail() {
        log.debug("send Email started");
        // read directory
        File directory = new File(attachmentFilePath);
        // get file from directory
        final File file = directory.listFiles(FILE_FILTER)[0];
 
        MimeMessagePreparator preparator = new MimeMessagePreparator() {
            public void prepare(MimeMessage mimeMessage) throws Exception {
                mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
                mimeMessage.setFrom(new InternetAddress(senderAddress));
                mimeMessage.setSubject("Neuer Report");
                // MimeMessagesHelper is needed for the attachment. The Boolean value in
                // constructor is for multipart/data = true
                MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
                helper.addAttachment(file.getName(), new FileSystemResource(file));
                helper.setText("Text in Email Body");
            }
        };
        try {
            this.mailSender.send(preparator);
            log.debug("send Email completed");
        } catch (MailException ex) {
            log.debug("send Email failed", ex);
        }
    }
 
    public static FileFilter FILE_FILTER = new FileFilter() {
        public boolean accept(File file) {
            return !file.isDirectory();
        }
    };
 }

package de.batch.mail;import java.io.File; import javax.ejb.Stateless; import javax.mail.Message; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.seam.annotations.Name; import org.springframework.core.io.FileSystemResource; import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessagePreparator;@Stateless @Name("SendMail") public class SendMailService {private static final Log log = LogFactory.getLog(SendMailService.class); private JavaMailSender mailSender; private String senderAddress; private String recipient; private String attachmentFilePath;// set the fields public void setFields(JavaMailSender mailSender, String senderAddress, String recipient, String attachmentFilePath) {this.mailSender = mailSender; this.senderAddress = senderAddress; this.recipient = recipient; this.attachmentFilePath = attachmentFilePath; }public void sendMail() { log.debug("send Email started"); // read directory File directory = new File(attachmentFilePath); // get file from directory final File file = directory.listFiles(FILE_FILTER)[0];MimeMessagePreparator preparator = new MimeMessagePreparator() { public void prepare(MimeMessage mimeMessage) throws Exception { mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(recipient)); mimeMessage.setFrom(new InternetAddress(senderAddress)); mimeMessage.setSubject("Neuer Report"); // MimeMessagesHelper is needed for the attachment. The Boolean value in // constructor is for multipart/data = true MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.addAttachment(file.getName(), new FileSystemResource(file)); helper.setText("Text in Email Body"); } }; try { this.mailSender.send(preparator); log.debug("send Email completed"); } catch (MailException ex) { log.debug("send Email failed", ex); } }public static FileFilter FILE_FILTER = new FileFilter() { public boolean accept(File file) { return !file.isDirectory(); } }; }

This is the tasklet, which calls the Service:

package de.batch.tasklets;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.mail.javamail.JavaMailSender;
 
import de.batch.mail.SendMailService;
 
public class SendMailTasklet implements Tasklet {
    private static final Log log = LogFactory.getLog(SendMailTasklet.class);
    private SendMailService sendMailService;
    private JavaMailSender mailSender;
    private String senderAddress;
    private String recipient;
    private String attachmentFilePath;
 
    public void setMailSender(JavaMailSender mailSender) {
       this.mailSender = mailSender;
    }
    public void setSenderAddress(String senderAddress) {
        this.senderAddress = senderAddress;
    }
 
    public void setRecipient(String recipient) {
        this.recipient = recipient;
    }
 
    public void setAttachmentFilePath(String attachmentFilePath) {
        this.attachmentFilePath = attachmentFilePath;
    }
 
    public void setSendMailService(SendMailService sendMailService) {
        this.sendMailService = sendMailService;
    }
 
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        log.debug("execute(StepContribution contribution, ChunkContext chunkContext) begin");
        sendMailService.setFields(mailSender, senderAddress, recipient, attachmentFilePath);
        sendMailService.sendMail();
        log.debug("execute(StepContribution contribution, ChunkContext chunkContext) end");
        return RepeatStatus.FINISHED;
    }
}

package de.batch.tasklets;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.mail.javamail.JavaMailSender;import de.batch.mail.SendMailService;public class SendMailTasklet implements Tasklet { private static final Log log = LogFactory.getLog(SendMailTasklet.class); private SendMailService sendMailService; private JavaMailSender mailSender; private String senderAddress; private String recipient; private String attachmentFilePath;public void setMailSender(JavaMailSender mailSender) { this.mailSender = mailSender; } public void setSenderAddress(String senderAddress) { this.senderAddress = senderAddress; }public void setRecipient(String recipient) { this.recipient = recipient; }public void setAttachmentFilePath(String attachmentFilePath) { this.attachmentFilePath = attachmentFilePath; }public void setSendMailService(SendMailService sendMailService) { this.sendMailService = sendMailService; }@Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { log.debug("execute(StepContribution contribution, ChunkContext chunkContext) begin"); sendMailService.setFields(mailSender, senderAddress, recipient, attachmentFilePath); sendMailService.sendMail(); log.debug("execute(StepContribution contribution, ChunkContext chunkContext) end"); return RepeatStatus.FINISHED; } }

Now you are able to send emails by your BatchJob with a CronJob.