A simple EmailerService
This tutorial provides some code for a simple Grails Service, "EmailerService", which allows you to send emails from your Grails applications.
The code was adapted from an example in the Spring documentation, so it also demonstrates integration with Spring-configured beans.
Of course there are plenty of alternative ways to do this kind of thing, for example, see
grails-app/conf/Notifications.groovy in the simple-cms Grails sample application.
First we configure a couple of beans in the Spring config file ( grails-app/conf/spring/resources.xml )that Grails provides for such things:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans><bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host"><value>mail.maurice.uk</value></property>
</bean> <!-- You can set default email bean properties here, eg: from/to/subject -->
<bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="from"><value>myapp@maurice.co.uk</value></property>
</bean>
<beans>
or the equivalent bean definition in resources.groovy:
mailSender(org.springframework.mail.javamail.JavaMailSenderImpl) {
host = 'mail.maurice.uk'
}// You can set default email bean properties here, eg: from/to/subject
mailMessage(org.springframework.mail.SimpleMailMessage) {
from = 'myapp@maurice.co.uk'
}
Then copy two jar files into the application local lib:
activations.jar and
mail.jar. These jar files are needed by org.springframework.mail.javamail.JavaMailSenderImpl.
Next the service itself. Note that the "mailSender" and "mailMessage" properties (Spring beans) are automagically injected by Grails.
import org.springframework.mail.MailException
import org.springframework.mail.MailSender
import org.springframework.mail.SimpleMailMessage/**
* Simple service for sending emails.
*
* Work is planned in the Grails roadmap to implement first-class email
* support, so there's no point in making this code any more sophisticated
*/
class EmailerService {
boolean transactional = false
MailSender mailSender
SimpleMailMessage mailMessage // a "prototype" email instance /**
* Send a list of emails
*
* @param mails a list of maps
*/
def sendEmails(mails) {
// Build the mail messages
def messages = []
for (mail in mails) {
// Create a thread safe "sandbox" of the message
SimpleMailMessage message = new SimpleMailMessage(mailMessage)
message.to = mail.to
message.text = mail.text
message.subject = mail.subject
messages << message
}
// Send them all together
try {
println "about to send ${messages.size()} messages to:n${messages.to.join('n')}"
mailSender.send(messages as SimpleMailMessage[])
} catch (MailException ex) {
println "Failed to send emails"
ex.printStackTrace()
}
}
}
Finally inject the service into a controller, build some emails, and send them:
/**
* Hit "http://localhost:8080/myapp/testEmails?to=me@somewhere.com&subject=hello+world&body=This+is+a+test" to send an email to yourself
*/
class TestEmailsController {
EmailerService emailerService // Send an email
def index = {
// Each "email" is a simple Map
def email = [
to: [ params.to ], // "to" expects a List, NOT a single email address
subject: params.subject,
text: params.body // "text" is the email body
]
// sendEmails expects a List
emailerService.sendEmails([email])
render("done")
}
}
You can of course also declare one service as a property of another, so you can also send emails from other services in the same way.