Pither.com

by Simon Pither, freelance developer and systems administrator

Envelope senders for Grails mail plugin (Spring Java Mail)

Posted by Simon Pither
1 Tue, 22 Jun 2010

I would have expected the desire to set a specific envelope sender address for mails from a web-app to be fairly common. However finding information on how to do it with the Grails mail plugin (ie Spring mail (wrappers for JavaMail)) proved much harder than I expected.

In fact, I ended up reading the source code!

It turns out that setting a single, application wide envelope sender is pretty easy (and is actually documented in various places). Simply set a value in Config.groovy such as:

grails.mail.smtp.from = "envelope@domain.com"

In my case though, I was looking to implement VERP for a mailing list, so that wasn't suitable.

From reading the source I discovered that the JavaMail SMTPTransport would actually check if the message it was given was an SMTPMessage and would respect the envelopeFrom property if it was.

To take advantage of this but still make use of the message builder from the mail plugin, I wrote a small service that wraps around the normal mailService:

import com.sun.mail.smtp.SMTPMessage
import javax.mail.internet.MimeMessage
import org.springframework.mail.MailMessage
import org.springframework.mail.javamail.MimeMailMessage
import org.grails.mail.MailMessageBuilder

class AdvancedMailService {
    static transactional = false

    def mailService
    def mailSender

    MailMessage sendMail(String envelopeFrom, Closure callable) {
        def messageBuilder = new MailMessageBuilder(mailService, mailSender)
        callable.delegate = messageBuilder
        callable.resolveStrategy = Closure.DELEGATE_FIRST
        callable.call()

        def message = messageBuilder.createMessage()
        mailService.initMessage(message)
        MimeMessage mimeMsg
        if(message instanceof MimeMailMessage)
            mimeMsg = message.getMimeMessage()
        else
            mimeMsg = message

        SMTPMessage smtpMsg = new SMTPMessage(mimeMsg)
        smtpMsg.envelopeFrom = envelopeFrom

        mailService.sendMail(smtpMsg)
        return message
    }
}

You have to call it as a specific service, but otherwise it's much the same as the normal mail service, eg:

advancedMailService.sendMail("list-recipient=theirdomain.com@domain.com") {
    from 'Mailing List <list@domain.com>'
    to "recipient@theirdomain.com"
    subject "Test mail"
    body(view: "/mails/test1", model: model)
    headers([
        'Precedence': 'bulk',
    ])
}

Now I just need to set something up to process the bounces. I wonder how easy it would be to embed James!?

Comments

  • 2 days ago, Helga said...
I'm about to implement VERP style bounce handling as well and found your post really useful. I'd go even further and let the service construct the envelop from the addressses. Did you think about contributing to the mail plugin? I think setting the envelop address is general functionality worth having there. It's easy to contribute as the grails-mail plugins sources have moved to github recently: http://github.com/gpc/grails-mail Just fork, tweak and issue a pull request.

Post a Comment