Email Testing on OSX

Yesterday I blogged about how I set up Groovy/Spring to send both HTML and plain text emails. Today I want to share a tip about testing those emails. I was using postfix on my Mac as SMTP server. This allowed Spring to connect to, and send the email, but the emails would never leave my machine. My coworker Sean had no problem with mail getting out, so I figured I either had some setting wrong or perhaps it was my cable company blocking the traffic.

I googled around a bit and came across this excellent blog article: fully local testing of email sending web apps (on Mac OS X)

This article describes how to set up postfix to listen to certain domain names and forward those emails to local account. It then goes on to describe how you can setup a pop3 server to get those mails.

The end result is that you can send email to anything at a particular domain and then use a desktop client to check the mail. This is not only cool for Groovy work but would also be useful for ColdFusion as well. I normally use Spoolmail to check CFML generated mail, but that isn't an option for Railo, and it doesn't give a 'perfect' end user view of the mail (especially for combo plain text/html emails like we are testing).

Plain Text and HTML Emails via Spring

Last week I had to add email support to our application. While this is trivial in ColdFusion, I was expecting quite a battle with Java. I had hoped that maybe Groovy would have a simple solution perhaps, but turns out it was even easier than I could imagine.

My experience with Spring has been pretty minimal. I know how to work with it, and I know how to add stuff and set dependencies and stuff, and so from that it meshed well with what I knew of ColdSpring. But Joe informed me that Spring was a lot more than just a Inversion of Control framework. It also ships with a set of additional features to help developers. So for example, scheduling stuff (which CFML developers get via the scheduler in the Admin) is easy with Spring. As you can probably guess, mail is easy as well.

I won't go into the full details here, but I'll point to the documentation on it and you can read it yourself.

Ok, so far so good. The problem I ran into though was moving from plain text messages to a mail message that supported both the plain text and html text at once. Here was the original code I had for the plain text message:


def subject = "Subject here..."
def emailStr =
"""
$user.firstName $user.lastName,

Etc etc
"""
def msg = new SimpleMailMessage(templateMessage)
msg.setTo(email)
msg.setText(emailStr)
msg.setSubject(subject)
    
try{
mailSender.send(msg)
}
catch(MailException ex) {
println(ex.getMessage())
}

The above should be easy enough to read. The templateMessage object is code injected by Spring and contains the connection information for the mail server (server, port, username, password). That stuff is configured in Spring which is sensible. I also configure the from there since all mail will be using one main from address. After that, all I have to do is set the subject, the To, and the text, then fire it off.

I had hoped that the setText method would perhaps have options for sending HTML email as well. Unfortunately that wasn't the case. (Hey, they did call it simple, didn't they?)

In all my searches at Google I was unable to find a simple example of this. I saw examples using attachments and HTML email, but not a plain+html example. The API docs for things I thought would be a good alternative were pretty confusing. My main issue was that everything wanted a MimeMessage object, and I couldn't figure out how to create it. Finally I realized that Spring had sent me a mailSender object (it's what I was using to send the mail) and had an option to create a mime message:


def msg = mailSender.createMimeMessage()

I could then use a MimeMessageHelper object like so:


def msg = mailSender.createMimeMessage()
def helper = new MimeMessageHelper(msg,true)
helper.setTo(email)
helper.setSubject(subject)
helper.setText(emailStr,htmlStr)
mailSender.send(msg)

That worked like a charm. I probably got half the terminology wrong above, but hopefully this will help others as well. A big thank you goes to Andrew Powell for his help on this.

Is it ColdFusion or Groovy?

Here at Broadchoice we've been working on our new product for close to three months now. I've gotten a crash course in Groovy, Spring, and Hibernate, all of which are slightly familiar to me from my time with ColdSpring, Transfer, and Java. I'm really digging these new technologies, but of course, I'm a die hard ColdFusion user at heart. A few weeks backs I needed to work on a quick iPhone web application prototype. Joe set up the connection and all I had to do was write CFML (lucky me). Little did I know that along with setting up basic CFML compatibility on the server, Joe also added one of the slickest things I've seen ever in my life as a developer.

The application I'm working on is pretty simple, but I wanted to use Model-Glue 3 for it since - well - you never know when a simple prototype will turn into a large, complex application. The following code snippet comes from a controller used to load bookmarks:


<cffunction name="getBookmarks" output="false">
<cfargument name="event" />
<cfset var u = arguments.event.getValue("currentuser")>

<!--- In theory currentuser should always exist, but... --->
<cfif not isSimpleValue(u)>
<!--- space only? --->
<cfif arguments.event.valueExists("space")>
<cfset arguments.event.setValue("bookmarks", beans.contentService.findContentBySpace(arguments.event.getValue("space"),["Bookmark"]))>
<cfelse>
<cfset arguments.event.setValue("bookmarks", beans.contentService.findUsersContent(u,["Bookmark"]))>
</cfif>
</cfif>

</cffunction>
Nothing in the above code should be too odd or even that exciting really. I'm using a service (injected via the beans scope in Model-Glue 3) to retrieve my content. My controller begins with...


<cfcomponent output="false" hint="I am a Model-Glue controller." extends="ModelGlue.gesture.controller.Controller"
beans="contentService,config"
>

Note the beans value specifies which beans configured in ColdSpring should be passed to my controller. I love this new automation in Model-Glue 3. If you open up my ColdSpring.xml file, you will see my beans configured:


<bean id="config" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
<property name="config">
<map>
<entry key="profileimageroot"><value>/some url you dont need to know</value></entry>
<entry key="filesroot"><value>/something else you dont need to worry about</value></entry>
<entry key="perpage"><value>10</value></entry>
</map>
</property>
</bean>

Hmmm. Ok, there's my config bean, wheres my contentService bean? Oh yeah - here it is:


<bean id="contentService" class="com.broadchoice.bcp.services.ContentService">
<property name="dao" ref="contentDAO"/>
<property name="sessionFacade" ref="sessionFacade" />
<property name="sharedFileGateway" ref="sharedFileGateway" />
<property name="eventMessageDispatcher" ref="eventMessageDispatcherService" />
</bean>

You can find the above in our Spring file. Just in case the above didn't quite make get through, let me make it real nice and obvious:


<cfset arguments.event.setValue("bookmarks", beans.contentService.findContentBySpace(arguments.event.getValue("space"),["Bookmark"]))>

The above line of CFML is using a bean injected from Spring, not ColdSpring, and points to a Groovy file. This is the same Groovy code used to drive the AIR application. No createObject("java") here baby. I'm using the Groovy code just like it had come from a CFC. This is done using a ColdSpring/Spring adapter that Joe wrote. It lets ModelGlue get Java-based beans from Spring. (I'm simplifying it here a bit, but hopefully you get the significance of that!) Once that connection is done, you can easily get beans from the Spring file and inject them into your controller. So for example, when my UserController wanted do handle login, I added: beans="userService,config" and then simply ran a userService.validateAndLoad on the authentication information.

It's always been easy to use Java from CFML, but never has been so sexy! Now to be fair, I did have to use a JavaCast once or twice, but not nearly as much as I would have thought.

Behind The Curtain

As you may have guessed from the content of our earlier blog posts, we're working on an AIR application that involves some sort of real-time collaboration. As you may also have guessed from the slower flow of postings since mid-August, we've been very busy working on that application!

Broadchoice Workspace blogWe're finally ready to start showing the world what we're working on and to talk about the concepts and technologies behind it. We're also taking early signups for the forthcoming limited beta program. [You can download the public release from the main Broadchoice website]

This blog post contains the first public unveiling of the application and its capabilities. The fundamental concept of the application is to provide a central way to collaborate with your colleagues (or friends). All users have a personal workspace containing files they have uploaded, a blog, a GTD-style task manager and useful bookmarks they have found.

[More]

AIR and Groovy via Spring

As a fun way to while away a Saturday evening, I decided to look at Joe's Behavioral Analytics backend code to see if I could create a Flex-based AIR application that talked to services written in Groovy. There's not really much documentation out there to help so it was a very hit and miss experience but eventually I had a simple AIR application making a RemoteObject call to a Groovy class and getting data back. I'm going to have to talk to Joe about cleaning up the installation I've ended up with but here are the highlights (and I'll blog more about this once I have all the pieces cleaned up):

  • JBoss 4.2.3 GA installed as a Server in Eclipse (using the Web Tool Platform JEE stuff)
  • Spring framework 2.5.5
  • A Spring-based Flex factory that allows Flex Remoting to talk to objects via Spring (author Jeff Vroom)
  • Groovy - set up per Joe's recent instructions
  • BlazeDS providing the Flex Remoting service
Create a Dynamic Web Project in Eclipse and then unzip BlazeDS into it (per the BlazeDS installation docs). Add Spring and the flex.samples.factories.SpringFactory Java class. Configure Flex Remoting according to Lin's instructions to add the Spring factory:

    <factories>
        <factory id="spring" class="flex.samples.factories.SpringFactory"/>
    </factories>
and the context loader:

    <!-- Spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <!-- load Spring's WebApplicationContext -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
and the destination for the RemoteObject:

<destination id="place">
        <properties>
            <factory>spring</factory>
            <source>placeholder</source>
        </properties>
</destination>

Create a Flex AIR project and define a RemoteObject that refers to the destination you just defined:


    <mx:RemoteObject id="bcp"
            destination="place"
            endpoint="http://127.0.0.1:8080/bcpbackend/messagebroker/amf"
            >

        <mx:method name="test" result="testResult(event)" fault="testFault(event)"/>
    </mx:RemoteObject>

Add the placeholder bean definition to your applicationContext.xml file:


    <bean id="placeholder" class="com.broadchoice.bcp.Placeholder"/>
com.broadchoice.bcp.Placeholder is a Groovy class that contains a test method (for testing it just takes a string and returns that string plus some additional text).

BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002. Contact Blog Owner