01 September 2006

Sending emails in Spring using Freemarker

Create a mail sender

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


Create the freemarker configuration

<bean id="freemarkerMailConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
<property name="templateLoaderPath" value="/WEB-INF/mail">
</bean>


Create a class for sending the mail:

public class InfoSenderMail implements InfoSender {

private Configuration configuration;
private String freemarkerTemplate;
private MailSender mailSender;

public void send() throws SendException {
SimpleMailMessage message = new SimpleMailMessage();

// Add stuff to them model for inserting into the template
final Map model = new HashMap();
model.put("name", "Tim");

// Merge the model into the template
final String result;
try {
result = FreeMarkerTemplateUtils.processTemplateIntoString(configuration.getTemplate(
freemarkerTemplate), model);
} catch (IOException e) {
throw new SendException(
"Unable to read or process freemarker configuration or template", e);
} catch (TemplateException e) {
throw new SendException("Problem initializing freemarker or rendering template '"
+ freemarkerTemplate + "'", e);
}

// Construct and send the message
message.setTo("someone@somewhere.com");
message.setSubject("Here is the info you requested");
message.setText(result);

mailSender.send(message);
}

public void setFreemarkerMailConfiguration(Configuration configuration) {
this.configuration = configuration;
}

public void setFreemarkerTemplate(String freemarkerTemplate) {
this.freemarkerTemplate = freemarkerTemplate;
}

public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}

}


Define the bean; the template should be in the location specified by templateLoaderPath (e.g. /WEB-INF/mail)


<bean id="infoSender" class="InfoSenderMail"
<property name="mailSender" ref="mailSender">
<property name="freemarkerMailConfiguration" ref="freemarkerMailConfiguration">
<property name="freemarkerTemplate" value="mytemplate.txt">
</bean>


Create the template. E.g. mytemplate.txt


Hello, ${name}!


Then simply inject the bean in another class and invoke send();

5 comments:

[mate] said...

Great tip. Do you know how to send HTML mail using this example?

Tim said...

Don't have an exact example, but basically change the send() method. Make your template HTML, then use Spring's MimeMessageHelper with setText([html content], true) to set the HTML content.

mschipperheyn said...

I'm getting Cannot convert value of type [freemarker.template.Configuration] to required type [org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean] for property 'freemarkerMailConfiguration': no matching editors or conversion strategy found

on this example. The reason is that it is expecting a Freemarker Configuration in stead of a FreemarkerConfigurationBean. Any ideas?

Marc

Tim said...

I'm not really sure. Is the code identical? I presume you kept the setter as:
public void setFreemarkerMailConfiguration(Configuration configuration) {
this.configuration = configuration;
}

The factory bean is supposed to return something of type Configuration. So the setter should accept that type. The error suggests otherwise.

jagan said...

What changes are required to include the images in templates? I know that including the spring.ftl in templates and using it to resolve the paths to images should work. Couldn't make this scenario working, any help would be greatly appreciated.