Sunday, January 28, 2007

Grails -- How to send out an email after some actions have been done?

In my work, I need to send out a notice to the administrators each time a user submit an application. There are several ways to do this. The example here just demonstrates how easy it can be done by using "afterInterceptor" just in couple of steps:

Step 1: Follow the tutorial posted here to configure a couple of beans which will be used for sending email.

In spring/resources.xml, add the following configurations:


<beanid="mailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl" >
<property name="host">
<value>mailServer.abc.com</value>
</property>
</bean>


Step 2: Copy three jar files into the application' local lib: activations.jar, mail.jar and javaee.jar. These jar files are needed by org.springframework.mail.javamail.JavaMailSenderImpl. which is registered in the above spring/resources.xml file.

Step 3: Add the following code into the controller that I want to intercept. Because I want to attach a PDF file, so I used MimeMessageHelper .


class ApplictionController {

/** the mailSender properties is defined in the spring/resources.xml and are automatically injected by Grails**/
MailSender mailSender

def afterInterceptor = [action:this.&sendMail,only:['save']]

def sendMail= {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

//recipient of email could be a list of email addresses
String [] to = new String[2]
to[0] = "address1@gmail.com"
to[1]= "address2@gmail.com"

helper.setTo(to)
helper.setSubject("It is a test")
helper.setText("check out this PDF file")

//attach a file
FileSystemResource file = new FileSystemResource(new File("/path/to/myApplication.pdf"));
helper.addAttachment("myApplication.pdf", file);

//send mail
mailSender.send(message)
}
...
...
...
}

Commentary:
1. One interceptor can be used to intercept more than one actions, for example:


def afterInterceptor = [action:this.&sendMail,only:['save', 'update']]



The Interceptor will execute each time after "save" or "update" are finished


2. The attachment could be binary data from the database. In this case, read data into a byte array and then create a ByteArrayResource from the byte array. The ByteArrayResource can be attached too.

3. We can intercept before some actions get executed basically the same way but using "beforeInterceptor" instead.

Issues: It turns out a very simple solution once I figured out how to do it. However, the solution above just intercepts actions based on a instance of one controller. What if I want to intercept multiple controller using only one interceptor? Can we do this in Grails?

1 comment:

Bhagwat Kumar said...

Thanks for your nice blog. I was looking for a solution to the scenario you solved in an easy way. During my search I studied various blogs regarding sending attachment with email, even tried the Grails Mail plug-in , but yours was good one. Another link that I found interesting is : -

http://www.java-tips.org/other-api-tips/javamail/how-to-send-an-email-with-a-file-attachment.html
It's purely a Java code and gives you full control over what is going behind the scene. Minor changes to the code can make it compatible to grails.