Posts Tagged ‘email’

ZTemplates email service

Friday, June 25th, 2010

Has been a while since I last blogged, but I have been rather busy lately. Today I have done what I wanted to be doing a long time ago. I wrote a ztemplates service for sending out emails, using the powers of the rendering engine to create HTML emails. So I came up with the following service (note that I wrote this for version 0.9.9.6):

public class ZEmailService implements ZIEmailService {
 
	@Override
	public void render(Object obj, final String from, final String[] recipients, final String subject) throws Exception {
		render(obj, from, recipients, subject, "text/html");
	}
 
	@Override
	public void render(Object obj, final String from, final String[] recipients, final String subject, String mimeType) throws Exception {
 
		if(obj.getClass().isAnnotationPresent(ZEmail.class) == false) {
			throw new Exception("@ZEmail annotation not present on " + obj.getClass().getCanonicalName());
		}
 
		final ZIRenderService renderService = ZTemplates.getRenderService();
		final ZEmail emailAnnotation = obj.getClass().getAnnotation(ZEmail.class);
		final Properties properties = new Properties();
		final String body = renderService.render(obj);
 
		properties.put("mail.smtp.host", emailAnnotation.host());
 
		if(emailAnnotation.username() != null) {
			properties.put("mail.user", emailAnnotation.username());
		}
		if(emailAnnotation.username() != null) {
			properties.put("mail.password", emailAnnotation.password());
		}
		sendMail(properties, from, recipients, subject, mimeType, body);
	}
 
	private static void sendMail(final Properties properties, final String from, final String[] recipients, final String subject, final String mimeType, final String body) throws MessagingException {
		final Session session = Session.getDefaultInstance(properties, null);
		final Message message = new MimeMessage(session);
		final InternetAddress addressFrom = new InternetAddress(from);
		final InternetAddress[] addressTo = new InternetAddress[recipients.length];
 
		for (int i = 0; i < recipients.length; i++) {
			addressTo[i] = new InternetAddress(recipients[i]);
		}
 
		message.setFrom(addressFrom);
		message.setRecipients(Message.RecipientType.TO, addressTo);
		message.setSubject(subject);
		message.setContent(body, mimeType);
 
		Transport.send(message);
	}
}

Here is the interface:

public interface ZIEmailService extends ZIService {
 
	  public void render(Object obj, final String from, final String[] recipients, final String subject) throws Exception;
	  public void render(Object obj, final String from, final String[] recipients, final String subject, String mimeType) throws Exception;
}

And the code for the @ZEmail annotation:

@Retention(RetentionPolicy.RUNTIME)
public @interface ZEmail {
	String host() default "localhost";
	String username();
	String password();
}

Let’s say we have a view like:

@ZRenderer(value = ZJspRenderer.class)
@ZEmail(password = "secret", host = "somehost", username = "admin")
public class SomeView {
 
    @ZExpose
    public String someValue() {
    }
}

As you can see the @ZEmail annotation makes it possible to set mail server settings. To actually send the mail using that view we only have to do the following:

new ZEmailService().render(new SomeView(), "from@example.org", new String[] { "to@example.org" }, "subject");

As you can see I’m not using the ServiceRepository in this example, I added the service to ztemplates myself, so I’m running a custom version. Just instantiating the service works as well.

There are of course a lot of improvements possible, but this version matches my needs. I hope someone will have some use of it.

Note: Will probably also work using other renderers, didn’t test it ;-)

Required external libraries:

  • mail.jar
  • activation.jar

Hope to be blogging some more soon.