Tuesday, January 20, 2009

Reliably sending email with Spring

Update 2009-09-12: I no longer recommend this library. Please see the comments.

My colleague Allard just pointed me to an old but very useful library: HA-JavaMail.

The email sender that the JVM provides has some serious shortcomings. It does not automatically open a new connection when the connection was closed and you can forward your e-mail to 1 SMTP server only. Furthermore, it is not so fast. HA-JavaMail circumvents these problems by wrapping the JVM implementation.

In this tiny article I explain how you configure HA-JavaMail from Spring. First make sure you have the HA-JavaMail jar, the Spring jar, the JavaMail mail.jar and the JAF activation.jar library on your classpath. The latter two are available by default in full JEE containers.

Convert your mail sender bean declaration from this:

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="mail.host" value="localhost"/> </bean>

to something like this:

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="javaMailProperties"> <value> mail.transport.host=localhost,mail.example.com mail.transport.pool-size=1 mail.transport.connect-timeout=0 mail.transport.connect-retry-period=60 mail.transport.sender-strategy=net.sf.hajavamail.SimpleSenderStrategy </value> </property> </bean>

Note that the example adds a second SMTP server that will be used when the first is unreachable. Only a value for mail.transport.host is required. The other values shown here are also the defaults.

That’s it. You now have a much more reliable and faster email service.

2 comments:

  1. It does look quite neat. But I did come across a thread saying that if errors do occur they are just logged, not thrown back to the client of the library:
    http://www.velocityreviews.com/forums/t522096-ha-javamail-not-handling-exceptions.html

    I checked the code in TransportProxy.java and on line 574 I can see:

    catch (SendFailedException e)
    {
    log.error("Failed to send message to invalid addresses: " + InternetAddress.toString(this.addresses), e);
    }

    So it's not quite System.out as it says in the post, but it doesnn't look great.

    Have you had any issues, would you still recommend it?

    ReplyDelete
  2. Wow, not nice. I read one other article that wrote that the code is a mess. I am no longer using it after an error on our production system. It turned out to be unrelated, but given these kind of reports, I never put it back.

    Conclusion: no, I no longer recommend this library.

    ReplyDelete