Provides Mail support to a running Grails application supported by Pivotal

64 votes

44% of Grails users

Dependency:
compile ":mail:1.0.7"

 Documentation  Source  Issues

Summary

This plug-in provides a MailService class as well as configuring the necessary beans within the Spring ApplicationContext.

It also adds a "sendMail" method to all controller classes. A typical example usage is:

sendMail { to "fred@g2one.com","ginger@g2one.com" from "john@g2one.com" cc "marge@g2one.com", "ed@g2one.com" bcc "joe@g2one.com" subject "Hello John" text "this is some text" }

Installation

To install the mail plug-in just run the following command

grails install-plugin mail

Description

Mail Plug-in

The mail plug-in provides e-mail sending capabilities to a Grails application by configuring a Spring MailSender based on sensible defaults.

There is a screencast showing how to use the basic features of the plugin (v0.4)

Usage

The mail plug-in provides a MailService that can be used anywhere in your Grails application. The MailService provides a single method called sendMail that takes a closure. In addition the sendMail method is injected into all controllers to simplify access.

An example of the sendMail method can be seen below:

sendMail {     
  to "fred@g2one.com"     
  subject "Hello Fred"     
  body 'How are you?' 
}

Or if you're using the service directly you can use:

mailService.sendMail {
   to "fred@g2one.com","ginger@g2one.com"
   from "john@g2one.com"
   cc "marge@g2one.com", "ed@g2one.com"
   bcc "joe@g2one.com"
   subject "Hello John"
   body 'this is some text'
}

To send HTML mail you can use the html method instead of the body method:

sendMail {
  to "fred@g2one.com"
  subject "Hello John"
  html '<b>Hello</b> World'
}

If your HTML is contained within a GSP template you can use the render tag called as a method (available in controllers and tag libraries):

sendMail {
  to "john@g2one.com"
  subject "Hello John"
  html g.render(template:"myMailTemplate")
}

If you wish to render a mail body from a GSP view from anywhere in your application, including from services or jobs where there may or may not be a current request, you can use the new body method variant (v0.4):

sendMail {
  to "john@g2one.com"
  subject "Hello John"
  body( view:"/emailconfirmation/mail/confirmationRequest", 
      plugin:"email-confirmation", 
      model:[fromAddress:'bill@microsoft.com'])
}

The view is the absolute path (or relative if you have a current controller) to the GSP. The plugin parameter is optional - if you need to render a template that may exist in a plugin installed in your application, you must include the name here. The model parameter is a map representing the model the GSP will see for rendering data.

In this case the content type will be auto-sensed - use the GSP page contentType directive to set the content-type to use in the e-mail. The default is text/plain so you must include this at the top of the GSP for a HTML email:

<%@ page contentType="text/html"%>

Note however that due to a limitation of the underlying Spring APIs used, XHTML content type text/xhtml will not result in a correct XHTML email.

This plugin also accepts emails in the form "Bill Gates<bill@microsoft.com>". This allows you to specify the sender display name in mail clients.

Multiple recipients

You can send mail to multiple recipients (in either of 'to', 'cc' or 'bcc') at once.

sendMail {
    to "fred@g2one.com","ginger@g2one.com"
    subject "Hello to mutliple recipients"
    body "Hello Fred! Hello Ginger!"
}

There is a pitfall when using a List for storing the recipients. You'll have to invoke toArray when providing it to the builder, like this:

sendMail {
    to issue.watchers.email.toArray()
    subject "The issue you watch has been updated"
    body "Hello Watcher!"
}

If you forget the call to toArray , Groovy will convert the list (even a list with a single entry) to a String (the same way it does on the interactive console). The result will be something that is not a valid email address and you'll face javax.mail.internet.AddressException .

Attachments

Since version 0.9 attachment support has been improved. It is possible to have both, email body and multiple attachments. In order to activate multipart support, the 'multipart true' must be the first element in the closure passed to the sendMail method, e.g.:

sendMail {
    multipart true
    to issue.watchers.email.toArray()
    subject "The issue you watch has been updated"
    body "Hello Watcher!"
    attachBytes "Some-File-Name.xml", "text/xml", contentOrder.getBytes("UTF-8")
    //To get started quickly, try the following
    //attachBytes './web-app/images/grails_logo.jpg','image/jpg', new File('./web-app/images/grails_logo.jpg').readBytes()
}

See also GRAILSPLUGINS-1175.

Asynchronous

The plugin can send mail asynchronously (the mail is sent on a different thread, and the sendMail message returns instantly, not waiting for the mail to be actually sent). In order to send asynchronously, 'async true' must be in the closure passed to the sendMail method, e.g.:

sendMail {
  async true
  to "john@g2one.com"
  subject "Hello John"
  html g.render(template:"myMailTemplate")
}

Configuration

By default the plugin assumes an unsecured mail server configured at localhost on port 25. However you can change this via the grails-app/Config.groovy file. For example here is how you would configure the default sender to send with a Gmail account:

grails {
   mail {
     host = "smtp.gmail.com"
     port = 465
     username = "youracount@gmail.com"
     password = "yourpassword"
     props = ["mail.smtp.auth":"true", 					   
              "mail.smtp.socketFactory.port":"465",
              "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
              "mail.smtp.socketFactory.fallback":"false"]

} }

And the configuration for sending via a Hotmail/Live account:

grails {
   mail {
     host = "smtp.live.com"
     port = 587
     username = "youracount@live.com"
     password = "yourpassword"
     props = ["mail.smtp.starttls.enable":"true", 
                  "mail.smtp.port":"587"]

} }

And the configuration for sending via a Yahoo account:

grails {
   mail {
      host = "smtp.correo.yahoo.es"
      port = 465
      username = "myuser"
      password = "mypassword"
      props = [ "mail.smtp.auth":"true",
                       "mail.smtp.socketFactory.port":"465",
                       "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
                       "mail.smtp.socketFactory.fallback":"false"  ]
   }
}

If your mail session is provided via JNDI you can use the jndiName setting:

grails.mail.jndiName = "myMailSession"

You can also set the default "from" address to use for messages in Config using:

// Since 0.2-SNAPSHOT in SVN
grails.mail.default.from="server@yourhost.com"

This will be used if no "from" is supplied in a mail. You can also disable mail delivery completely in certain environments by setting@grails.mail.disabled@:

grails.mail.disabled=true

This is useful for certain environments where you don't want mails to be delivered such as during testing. Another useful setting often set per-enviroment is @grails.mail.overrideAddress@which lets you override the email address mails are sent to and from:

grails.mail.overrideAddress="test@address.com"

You can also adjust the size of the asynchronous mail sending thread pool. This size is the maximum number of threads that can send mail concurently. By default the value is 5 - so there could be 5 emails being sent asynchronously at the same time (if any more are sent, they will be queued). Note that is only used when sending mail asynchronously.

grails.mail.poolSize=5

TODO

  • Attachment support
  • Support for multiple parts
  • Support for MailSender artefact and sendMail(with: 'defaultSMTP') {..} for multiple smtp servers
  • Inline images
  • etc.

Troubleshooting

  • If an installation failed because of unresolved dependencies ...
    (like "javax.activation#activation;1.1: not found"
    … check if mavenCentral() is uncommented in your BuildConfig.groovy
  • If you face javax.mail.internet.AddressException errors referring to "Illegal address in string" or "Missing ']' in string", it could be that you try to send to a List of recipients, which is not supported by the plugin. See 'Multiple recipients' above for information how to deal with that.
  • If you call sendMail in a service class rendering a gsp template, you may realize that the plugin is rendering the template as text/plain instead of html. To solve this issue you have to put in your gsp <%@ page contentType="text/html" %> or <%@ page contentType="text/xhtml" %> without setting the encoding