This brief tutorial will show how to send e-mail using Spring and JavaMail. JavaMail can handle e-mail storage as well, but here we're just worrying about sending e-mail.
I happen to be using Spring 2.5 but this ought to work for earlier versions of Spring as well (at least Spring 2.0 I think).
Let's jump right in. You can configure your JavaMail session either in Spring itself or with JNDI. We'll look at both alternatives.
Alternative 1: Configuring JavaMail with Spring
You may be operating in an environment where you don't have a JNDI enterprise naming context (ENC) available. Or you may have some reason not to use it even if you do have a JNDI ENC. For example, I've written a simple application monitor, and I'll be adding e-mail alerting shortly. This is a standalone app and so there's no JNDI ENC. No problem; I can just configure JavaMail in the Spring application context configuration as shown below.
<!-- Mail service --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="your.smtphost.com"/> <property name="port" value="25"/> <property name="username" value="yourusername"/> <property name="password" value="yourpassword"/> <property name="javaMailProperties"> <props> <!-- Use SMTP-AUTH to authenticate to SMTP server --> <prop key="mail.smtp.auth">true</prop> <!-- Use TLS to encrypt communication with SMTP server --> <prop key="mail.smtp.starttls.enable">true</prop> </props> </property> </bean>
This bean is, as its name suggests, a mail sender. It is basically a wrapper around JavaMail SMTP, and the configuration reflects that. In the example I'm showing how you would enable SMTP-AUTH (supports authentication to the SMTP server) and TLS (supports message encryption), assuming your SMTP server has those capabilities. For more information see my article SMTP and SMTP-AUTH.
IMPORTANT: You will need to inject
mailSender into your mail-sending service bean.
So that's how to configure JavaMail from Spring. Now here's how to do the same thing with JNDI, which you may want to do if you're running in an environment with a JNDI ENC (like an app server or a servlet container).
Alternative 2: Configuring JavaMail with JNDI
Server JNDI configuration (using Tomcat 6 as an example)
First you will need to expose a JavaMail session factory through JNDI in your server environment. This is environment-dependent, but let's look at an example.
Say you're using Tomcat 6. There are a couple things you must do. First, move
activation.jar to your
tomcat/lib directory. I say "move" rather than "copy" because you will get an odd error if you leave the two JARs in your application classpath. The error is
java.lang.IllegalArgumentException: Cannot convert value of type [javax.mail.Session] to required type [javax.mail.Session] for property 'session': no matching editors or conversion strategy found
Second, define your Tomcat JNDI configuration, which might look like this (e.g. in your
<?xml version="1.0" encoding="UTF-8"?> <Context path="/myapp" docBase="myapp" debug="5" crossContext="false"> <!-- JavaMail session factory --> <Resource name="mail/Session" auth="Container" type="javax.mail.Session" username="yourusername" password="yourpassword" mail.debug="true" mail.user="yourusername" mail.password="yourpassword" mail.transport.protocol="smtp" mail.smtp.host="your.smtphost.com" mail.smtp.auth="true" mail.smtp.port="25" mail.smtp.starttls.enable="true"/> </Context>
As with the non-JNDI example, I'm configuring for SMTP-AUTH and TLS. If you are using SMTP-AUTH (authenticated SMTP sessions, which you activate using
mail.smtp.auth="true"), then you will need to specify the username and password twice, as shown above. Also, if your SMTP server supports it, you can tell JavaMail to encrypt sessions using TLS by setting
The above discussion applies only to Tomcat 6 (see Apache Tomcat 6.0 JNDI Resources HOWTO for detailed instructions); you'll need to consult your server docs to expose a JavaMail session factory through JNDI in your environment.
We still need to create a mail sender, but the configuration is simpler since we did all the heavy lifting in
context.xml (or whatever, depending on your server environment). So for the Spring application context, all we need is:
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="session" ref="mailSession"/> </bean>
IMPORTANT: As before, you will need to inject
mailSender into your mail-sending service bean.
So that takes care of configuring the mail sender, and also the JavaMail session factory if you are using JNDI. Let's visit one more topic before we dive into the code itself.
Creating an E-mail Template (Optional)
Sometimes the e-mail you want to send fits inside a standard template (e.g., maybe it always has the same sender, or maybe the same recipient, or whatever). You can define a template using Spring. Here's an example:
Spring app context config file
<!-- Mail message --> <bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage"> <property name="from"> <value><![CDATA[Simple Application Monitor <firstname.lastname@example.org>]]></value> </property> <property name="to"> <value><![CDATA[System Administrator <email@example.com>]]></value> </property> <property name="subject" value="SAM Alert"/> </bean>
You can include as many e-mail templates in a Spring app context configuration, including none if you don't need a template. Here I've defined a template that specifies a "from" field, a "to" field and a "subject" field. It doesn't specify the date or the body. That template works say for an application monitoring system but it wouldn't work for an e-commerce site's order confirmation e-mail, which would need to have a variable "to" field.
IMPORTANT: I didn't show it above, but you will need to inject any e-mail templates (i.e. mail messages) you create into your mail-sending service bean. Otherwise the service bean has no way to use the template.
So that's that. Time for the Java code that actually sends the e-mail.
How to Send the E-mail from Your Service Bean
It turns out that the coding part is much simpler than the configuration (not that the config was too bad). Let's suppose for the sake of example that we want to send an e-mail based on the template that we defined above, and that you've injected that template into your service bean as
mailMessage. Then here's the service bean code that allows you to use the template to send an e-mail:
Your service bean
SimpleMailMessage message = new SimpleMailMessage(mailMessage); message.setSentDate(new Date()); message.setText("Blah blah blah..."); mailSender.send(message);
You can see we're creating a new message based on the
mailMessage e-mail template and
mailSender that we injected into said service bean.
And that's it! Not too painful, right?
by Willie Wheeler