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!?