Pither.com / Simonhttps://www.pither.com/simon/blog/2013-11-19T14:08:44+00:00Development, systems administration, parenting and businessAdd an SMTP server to a Grails application2011-09-20T00:00:00+00:002013-07-29T13:50:23+00:00Simon Pitherhttps://www.pither.com/simon/blog/2011/09/20/add-an-smtp-server-to-a-grails-application<article>
<h1>Add an SMTP server to a Grails application</h1>
<div class="article-meta">
Posted
by <span>Simon Pither</span>
on <time datetime="2011-09-20T00:00:00+00:00">Tue 20th Sep 2011</time>
(updated <time datetime="2013-07-29T13:50:23+00:00">Mon 29th Jul 2013</time>)
</div>
<div>
<p>Quite a long time ago I talked about <a href="http://www.pither.com/articles/2010/06/22/envelope-senders-for-grails-mail-plugin-spring-java-mail">setting envelope sender addresses</a> so that I could send mailshots and get back any bounces in a useful way. The missing component to it was to process those bounces within my application. Here, finally, is my write up of how I did this.</p>
<p>After much searching I eventually found the excellent <a href="http://code.google.com/p/subethasmtp/">SubEtha SMTP</a> project which made including an SMTP server within my Grails application incredibly easy. Just four simple steps are required...</p>
<p>Include the library (grails-app/conf/BuildConfig.groovy):</p>
<pre><code>dependencies {
compile('org.subethamail:subethasmtp:3.1.4') {
excludes 'mail'
}
}
</code></pre>
<p>Write a SubEtha message listener (for me: src/groovy/com/supajam/smtp/MessageListener.groovy):</p>
<pre><code>package com.supajam.smtp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.subethamail.smtp.TooMuchDataException;
import org.subethamail.smtp.helper.SimpleMessageListener
import com.supajam.BounceRecord
public class MessageListener implements SimpleMessageListener {
private final static Logger log = LoggerFactory.getLogger(MessageListener.class);
public boolean accept(String from, String recipient) {
return true;
}
public void deliver(String from, String recipient, InputStream data) throws TooMuchDataException, IOException {
// I use this to process bounce messages, but it's just an
// email message that could be processed however you like
BounceRecord.withTransaction {
if (log.isDebugEnabled())
log.debug("Processing mail from " + from + " to " + recipient);
// The regex on the next line is specific to my VERP scheme
def origAddr = recipient =~ /-(.+=.+)@/
if(origAddr && origAddr[0].size() > 1) {
// here I extract the source address, ensure it's
// valid, record the bounce and remove the address
// from the mailing list.
}
}
}
}
</code></pre>
<p>I've included an outline of the code that I actually use to process incoming email - all of which I know will be bounce messages. There's nothing to force this use though, it's just a generic way to receive emails into an application.</p>
<p>Wire it together with Spring (grails-app/conf/spring/resources.groovy):</p>
<pre><code>beans = {
// Create an in-process SMTP server for processing bounces
smtpMessageListener(com.supajam.smtp.MessageListener)
smtpMessageListenerAdapter(org.subethamail.smtp.helper.SimpleMessageListenerAdapter, ref('smtpMessageListener'))
smtpServer(org.subethamail.smtp.server.SMTPServer, ref('smtpMessageListenerAdapter')) {
port = 2500
hostName = "my.server.name"
disableTLS = true
maxConnections = 10
}
}
</code></pre>
<p>To avoid running my grails application as root, I set the SMTP port to a high number (2500 in this example). Getting emails delivered to such a port is beyond this post (but personally I use iptables redirects).</p>
<p>Finally, make it run at application start (grails-app/conf/BootStrap.groovy):</p>
<pre><code>class BootStrap {
def smtpServer
def init = { servletContext ->
log.debug("Starting SMTP server")
try {
smtpServer.start()
}
catch(Exception e) {
// Starting the web application is more important
// than SMTP, so just log the failure and carry on
log.error("SMTP server could not be started")
}
}
def destroy = {
log.debug("Stopping SMTP server")
smtpServer.stop()
}
}
</code></pre>
<p>I guard the SMTP server start just in case there's a problem. No SMTP server is a nuisance but no web application is very bad. Just for cleanliness I also attempt to stop it in the destroy method.</p>
<p>That's it! It really is that simple to have a full SMTP server running within grails and ready to accept and process incoming email.</p>
</div>
<div class="tags-panel panel panel-default">
<div class="panel-body">
Tags:
<a rel="tag" href="/simon/blog/?tag=grails">grails</a>
<a rel="tag" href="/simon/blog/?tag=email">email</a>
<a rel="tag" href="/simon/blog/?tag=smtp">smtp</a>
<a rel="tag" href="/simon/blog/?tag=technology">technology</a>
</div>
</div>
</article>
grails-mail patch for envelopeFrom (VERP)2011-03-13T00:00:00+00:002013-11-19T14:08:44+00:00Simon Pitherhttps://www.pither.com/simon/blog/2011/03/13/grails-mail-patch-for-envelopefrom-verp<article>
<h1>grails-mail patch for envelopeFrom (VERP)</h1>
<div class="article-meta">
Posted
by <span>Simon Pither</span>
on <time datetime="2011-03-13T00:00:00+00:00">Sun 13th Mar 2011</time>
(updated <time datetime="2013-11-19T14:08:44+00:00">Tue 19th Nov 2013</time>)
</div>
<div>
<p>I have previously written about <a href="/articles/2010/06/22/envelope-senders-for-grails-mail-plugin-spring-java-mail">setting envelope senders when sending email in grails</a> and following comments made on that post I did actually get around to submitting a patch to the plugin.</p>
<p>However a change to that patch was suggested and before I managed to implement it, the mail plugin underwent a fairly large refactoring which meant I needed to completely rework my patch.</p>
<p>The refactoring did actually make my updated patch much simpler though and I have now got it all written, complete with test coverage (my first go at using <a href="http://www.icegreen.com/greenmail/">GreenMail</a> - which I quite like).</p>
<p>This time around my patch adds an envelopeFrom method to the sendMail closure...</p>
<pre><code>sendMail {
envelopeFrom 'verp-fred=smith.com@example.com'
from 'abc@example.com'
to 'fred@smith.com'
subject 'Important email'
body ...
}
</code></pre>
<p>You can find <a href="https://github.com/spither/grails-mail">my version of the grails mail plugin</a> forked on github and hopefully it will be <a href="https://github.com/gpc/grails-mail/pull/3">pulled</a> into the main plugin soon.</p>
<p>It's already in production and working well at <a href="http://www.supajam.com/">SupaJam</a> (sending about 50,000 emails per week).</p>
</div>
<div class="tags-panel panel panel-default">
<div class="panel-body">
Tags:
<a rel="tag" href="/simon/blog/?tag=grails">grails</a>
<a rel="tag" href="/simon/blog/?tag=email">email</a>
<a rel="tag" href="/simon/blog/?tag=smtp">smtp</a>
<a rel="tag" href="/simon/blog/?tag=envelope-sender">envelope sender</a>
<a rel="tag" href="/simon/blog/?tag=verp">verp</a>
<a rel="tag" href="/simon/blog/?tag=technology">technology</a>
</div>
</div>
</article>
Envelope senders for Grails mail plugin (Spring Java Mail)2010-06-22T00:00:00+00:002013-07-29T13:54:32+00:00Simon Pitherhttps://www.pither.com/simon/blog/2010/06/22/envelope-senders-for-grails-mail-plugin-spring-java-mail<article>
<h1>Envelope senders for Grails mail plugin (Spring Java Mail)</h1>
<div class="article-meta">
Posted
by <span>Simon Pither</span>
on <time datetime="2010-06-22T00:00:00+00:00">Tue 22nd Jun 2010</time>
(updated <time datetime="2013-07-29T13:54:32+00:00">Mon 29th Jul 2013</time>)
</div>
<div>
<p>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 <a href="http://grails.org/plugin/mail">Grails mail plugin</a> (ie Spring mail (wrappers for JavaMail)) proved much harder than I expected.</p>
<p>In fact, I ended up reading the source code!</p>
<p>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:</p>
<pre><code>grails.mail.smtp.from = "envelope@domain.com"
</code></pre>
<p>In my case though, I was looking to implement <a href="http://cr.yp.to/proto/verp.txt">VERP</a> for a mailing list, so that wasn't suitable.</p>
<p>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.</p>
<p>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:</p>
<pre><code>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
}
}
</code></pre>
<p>You have to call it as a specific service, but otherwise it's much the same as the normal mail service, eg:</p>
<pre><code>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',
])
}
</code></pre>
<p>Now I just need to set something up to process the bounces. I wonder how easy it would be to embed <a href="http://james.apache.org/">James</a>!?</p>
<p>Update: <a href="/articles/2011/03/13/grails-mail-patch-for-envelopefrom-verp">revised approach</a>, complete with patch sent to grails-mail plugin.</p>
<p>Update: I didn't use James, but I did finally <a href="/articles/2011/09/20/add-an-smtp-server-to-a-grails-application">accept SMTP mail in Grails</a>.</p>
</div>
<div class="tags-panel panel panel-default">
<div class="panel-body">
Tags:
<a rel="tag" href="/simon/blog/?tag=grails">grails</a>
<a rel="tag" href="/simon/blog/?tag=email">email</a>
<a rel="tag" href="/simon/blog/?tag=smtp">smtp</a>
<a rel="tag" href="/simon/blog/?tag=envelope-sender">envelope sender</a>
<a rel="tag" href="/simon/blog/?tag=spring">spring</a>
<a rel="tag" href="/simon/blog/?tag=technology">technology</a>
</div>
</div>
</article>