Saturday, November 1, 2014

Sending Email with Spring

Sending Email with Spring

At work, we were using an in-house dependnecy to send text-based internal emails out the door of one our webapps for notifications. The solution worked will for us, but did more than just send emails. As a result, depending on it introduced a large dependency tree to our application.

Since the artifact simply appeared to be a wrapper around Spring, which we were using directly anyway, we thought it might be better to write our own little solution instead, and simplify our application's dependency graph.

Below I'll describe some "highlights". A full project example can be found here: spring-mail-example

In our business processes, we send notifications to same email address and from the same sender. The only thing that may change is the subject of the email (success vs. failure) and the contents of the email. So we wanted a simple interface that just took both these parameters:

interface Sender {
    void send(String subject, String text)
}

Below is an implementation of the interface that:

  • Sends a simple MimeMessage with type text/html.
  • Expects the sender and recipient email address to be injected.
  • Expects the name and port of the mail host to use to be injected.
  • Creates an instance of JavaMailSender to help simplify configuration for the user.

The code:

class EmailSender implements Sender, InitializingBean {

    String mailHost
    int mailPort
    String fromAddress
    String toAddress

    protected JavaMailSender mailSender

    @Override
    void send(String subject, String text) {
        try {
            mailSender.send htmlMessageWith(subject, text)
        }
        catch (e) {
            logFailure e
            throw new MessageException(e)
        }

        logSent toAddress, subject, text
    }

    private MimeMessage htmlMessageWith(subject, text) {
        def mimeMessage = new MimeMessage(null)
        def messageHelper = new MimeMessageHelper(mimeMessage)

        messageHelper.with {
            addTo toAddress
            setFrom fromAddress
            setSubject subject
            setText text, true
        }

        messageHelper.mimeMessage
    }

    @Override
    void afterPropertiesSet() throws Exception {
        mailSender = new JavaMailSenderImpl()
        mailSender.setHost mailHost
        mailSender.setPort mailPort
    }
}

An example of how to configure the implementation with Spring:

    <bean class="prystasj.spring.mail.EmailSender">
       <property name="fromAddress" value="prystasj@company.org"/>
       <property name="toAddress" value="friend@company.org"/>
       <property name="mailHost" value="mailhost.company.org"/>
       <property name="mailPort" value="25"/>
   </bean>

In the end, we decided to go with this solution for our emails. While we now have code of our own to maintain, the resulting dependency tree is smaller, and we have control over adding any features we want, so for now the trade-off is worth it.

No comments:

Post a Comment