Welcome to the next entry in the Best of ColdFusion 9 Contest. Today's entry is GView by Ben Nadel. This entry was reviewed by Daniel Short (and as before, I'll chime in here and there and interpret some of his comments). GView is a simple GMail viewer. It makes use of ColdFusion 9's new IMAP support primarily, but also hits the caching system, VFS, and other new features. Note: Ben was nice and sent us a pre-configured configuration for a demo GMail account. I've removed those credentials from the zip. You can find the settings within the Application.cfc file and they must be updated if you want to test the code.
So what did Daniel like?
- No cfscript components (YAY FOR TAGS!)
- Lots of new caching functionality to build an email reader with no local storage. No database needed for this one.
- New isNull checks for dealing with empty mail folders.
- I believe he may have used every imap function available :-).
- Implicit getters and setters with cfproperty
- Did I mention lots of caching?
Ben points out that some functionality is missing in the demo - the big one being able to reply to email messages. But dang - for an incomplete application it works well and has a very clean UI. This is the default view:

And this is the compose message UI:

I can't explain exactly why - but I really, really like the design. Daniel went on to say:
While the app at it's core is very simple (read and write emails), the implementation is very well done and easy to understand. There are just a few external points of contact with the front end UI, which would make it easy to wrap up this functionality for use just about anywhere.
I think that is pretty accurate. The code is very clear and concise (well, not vertically concise, like most of Ben's code it goes vertical in a big way).
If I had to get picky, one thing I don't like is the use of this.X() method calls within a CFC. Whenever you are inside a CFC and call an internal method via this.X() you run the risk of being blocked if the method is private. I've pinged Ben on this before but I think it's just a personal preference of his. (Ben, that is cue to set me right!)
Oh - here is something slick. Not new to ColdFusion 9, but not used by very many people, Ben makes use of attributeCollection when running his IMAP calls. So for example:
<cfimap
name="local.message"
action="delete"
uid="#arguments.uid#"
folder="#arguments.folder#"
attributecollection="#this.getImapConfig()#"
/>
All the boring config data is abstracted out of the call and you focus just on the particular action. Handy.
Lastly - when I downloaded an attachment, the zip extracted to a 0 length file. Anyone else have an issue with attachments?
Another nice little touch - note the dynamic application name:
<cfset this.name = hash( getCurrentTemplatePath() ) />
Most of my OS applications use a method like this to name themselves. By hashing the current path you are guaranteed a unique name per server. If he had used something simple like "gview", it's possible that another application on the server may use the same name.
Anyway - that's it. As always, keep the comments friendly, download it, and check it out by clicking the download link below.
Archived Comments
Even with just these two entries published thus far, this is awesome to follow through these apps as a new CF developer. Learning a lot. Thanks to you all.
"No cfscript components (YAY FOR TAGS!)"
That's funny, I thought this was "The Best of ColdFusion 9 Contest" not "The Best of DBML" :)
Cool project Ben, the UI looks slick!
First off, thanks for letting me participate in this stuff :) It was a lot of fun.
As far as the THIS-scoping in my internal method calls, this is a personal preference thing. For some reason, and maybe this is a carry over from Javascript, but I just have this huge urge to scope ALL of my method calls. Seeing a method just sitting out there, alone, without any scope just sort of makes me sad :)
Of course, this leads to another issue - pre CF9, you couldn't scope private methods AND use named-arguments. IE. the following would throw an error:
variables.doSomething( foo = "bar" )
As such, I simply made all of my methods public such that I could use the THIS scope when invoking them.
I have to say, though, even with this variables-scope issue being fixed in CF9, scoping private method calls might take some getting used to as I simply don't like typing out "variables". I guess I am lazy that way. Plus, I don't think it looks nice.
Nice and sleek. No wai to lost yourself in Ben's code.
I always appriciated when ppl are able to do things that way, regartless the fact I never was :)
(this is the place where I say "good bless framewroks")
As regular reader of his blog, I used to on his coding style. Dynamic app name is kinda of his signature.
I tried to open my GMail account, which holds gazillion of emails, and app breaks on <cfimap action="getall".../>.
But it works when I limit number of emails to retreive (ie MaxRows=50).
+1 prefixing vars with "variables" sucks
+1 don't like "this" scoping of methods
+1 Latest Muse album is brilliant
As consequence of its artistic simplicity, app is bug free ;)
Cool app Ben. I had to set maxrows as suggested by Marko but then it worked great.
Oooh right, maxrows. Yeah, the test account I was working with only had like 3 emails in it :)
To clarify, is Dan saying that he prefers tag based CFCs versus those that use cfscript?
@MIke: Who is this Dan you speak of?
The entry was reviewed by Dan Short. About 70% of the 16 entries are being judged by other members of the Adobe Community Experts program. I'm taking their reviews in, massaging them a bit, and posting them. Make sense?
Yes. Yes it does.
Great app! It was exactly what I was looking for. I was able to add "Sent Mail" also. You can do this by modifying a cfimap to look in folder="[Gmail]/Sent Mail"