Mail Plugin

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)

Installation

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

grails install-plugin mail

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/html so you must include this at the top of the GSP for a plain text email:

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

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.

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 .

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"]

} }

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.

TODO

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

Troubleshooting

  • 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.

7 Comments

  • Gravatar
    It is better to use a different scope name for the configuration. If we use
    grails {
      mail {
        …
      }
    }
    All settings defined in Config.groovy before the mail configuration will be overridden. For example, grails.serverURL will be empty. I think it is sufficient to use mail as the top level scope, e.g. @mail.default.from@, @mail.host@, etc.
    May 11, 2009 08:05 AM sjtai
  • Gravatar
    Hi, I need to install the mail plugin manually. Can you please provide a .zip version of the plugin

    Thanks in advance

    May 18, 2009 04:05 AM slacksn
  • Gravatar
    no longer needed. thx
    May 18, 2009 10:05 AM slacksn
  • Gravatar
    You can either add other configuration items into the grails closure like the example or just add some straight lines as below, this way you will not lose anything.

    //mail plugin grails.mail.host="smtp.gmail.com" grails.mail.port=465 grails.mail.username="support@xxx.com" grails.mail.password="xxx" grails.mail.props="mail.smtp.auth": "true", "mail.smtp.socketFactory.port": "465", "mail.smtp.socketFactory.class": "javax.net.ssl.SSLSocketFactory", "mail.smtp.socketFactory.fallback": "false" (+) grails.mail.default.from="support@xxx.com"

    May 28, 2009 07:05 AM mengjun.jiang
  • Gravatar
    Whenever I try to use something like

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

    I get the Exception

    org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: java.lang.String.call() is applicable for argument types: (java.util.LinkedHashMap) values: [view:/tracker/deal_alert, model:[results:[.... (+)]

    Any ideas?

    Jun 25, 2009 14:06 PM slippytoad
  • Gravatar
    Apologies, I fixed my problem. A variable name was conflicting.
    Jun 25, 2009 20:06 PM slippytoad
  • Gravatar
    I'm having trouble getting this plug-in to work on Amazon EC2. It works great in my development environment.

    The email SMTP servers I've tried are GMail and AuthSMTP. I get the mail connection can't be opened error message. Thoughts? Anyone else have the same issue?

    Jun 29, 2009 03:06 AM skymasterson

Post a Comment