Connecting to Gmail using ColdFusion

Nov 27, 2007

Do you want to build an integrated ColdFusion interface to Gmail?  Using newbish's IMAP CFC client, it can be done.  It just needs a couple modifications to work with Gmail's SLL IMAP.  

Here's how...

1. Enable IMAP in your Gmail account
2. Download the IMAP CFC from SourceForge.
3. Make the following modifications to the imap.cfc

  • On line 7, add this... <cfset this.sslenabled = 0 />
  • At the end of the init() function, add this...
            <cfif isdefined("arguments.ssl")>
                <cfset this.sslenabled = 1 />
            </cfif>
  • Replace the GetStore() function with this one...
        <cffunction name="GetStore" access="private" output="No">
            <cftry>
            <cfset clsSession = createObject("Java", "javax.mail.Session")>
            <cfset objProperties = createObject("Java", "java.util.Properties")>
            <cfset objStore = createObject("Java", "javax.mail.Store")>
            <cfset Timeout = this.imapTimeout * 1000>
            <cfif this.sslenabled>
                <cfset protocol = "imaps">
            <cfelse>
                <cfset protocol = "imap">
            </cfif>
            <cfset objProperties.init()>
            <cfset objProperties.put("mail.store.protocol", protocol)>
            <cfset objProperties.put("mail.imap.port", this.imapPort)>
            <cfset objProperties.put("mail.imap.connectiontimeout", Timeout)>
            <cfset objProperties.put("mail.imap.timeout", Timeout)>
            <cfset objSession = clsSession.getInstance(objProperties)>
            <cfset objStore = objSession.getStore()>
            <cfset objStore.connect(this.imapServer, this.username, this.password)>
            <cfcatch type="any">
                You do not have a mail account or there was a problem authenticating.<cfabort>
            </cfcatch>
            </cftry>
            <cfreturn objStore>
        </cffunction>


You can now use the CFC library to interface with Gmail's IMAP.  Just make sure to pass the right arguments into the init function - The port has to be 993 for Gmail, and argument 6 should be a 1 (ssl enabled).  The CFC will still work for non-SSL IMAP calls if you want to use it. Just pass a 0 in argument 6.

Here's an example for Gmail...

<!--- Written by Jason Quatrino, Hamilton College // --->
<cfset imapCFC = CreateObject("component","imap") />
<cfset imapInit = imapCFC.Init(username,password,"imap.gmail.com",993,15,1) /><!--- add your own username/password --->
<!--- determine which message ids to get --->
<cfset msgs = imapCFC.list("Inbox") />
<!--- Return a query of messages --->
<cfdump var="#msgs#" />

If you have a TON of e-mail in your Gmail Inbox, you might want to modify this code before you run it.  Something like this... pass in just a few message IDs in the second argument of the list function.  I can share more code if people are interested, but I don't have permission from "newbish" to post the whole CFC.

Comments

Brian

Brian wrote on 11/27/07 9:33 AM

Great article, thanks for sharing this with us.
David

David wrote on 12/03/07 2:48 PM

I am interested in your idea for passing in multiple message IDs...can you share the code for this?
Mike

Mike wrote on 12/03/07 3:22 PM

This code should give you back your last 10 messages by using a list of IDs.

<cfset imapCFC = CreateObject("component","imap") />
<cfset imapInit = imapCFC.Init("username","password","imap.gmail.com",993,15,1) />            
            
<cfset foldername = "Inbox" />
<cfset limit = "10" />
<cfset msgIDs = "">   

<!--- Get a count of messages in the folder // --->
<cfset msgcount = imapCFC.count(foldername) />
            
<!--- determine how many messages to get --->      
<cfif msgcount LTE limit>
<cfset to=msgcount />
<cfelse>
<cfset to=limit />            
</cfif>

<!--- build list of message ids --->
<cfloop from="1" to="#to#" step="1" index="i">
   <cfset msgIDs = ListAppend(msgIDs,i) />
</cfloop>

<!--- get headers for message id list --->
<cfset msgs = imapCFC.list(foldername,msgIDs) />
<cfdump var="#msgs#">
Ryan

Ryan wrote on 01/07/08 10:20 PM

Line 10 on my imap.cfc is a bunch of comments. The cfcomponent tag doesn't start until line 68. Can you be more specific as to where the cfif isdefined("arguments.ssl") line is supposed to go?

Does it go anywhere in the init function?

thanks
Michael Sprague

Michael Sprague wrote on 01/08/08 6:48 AM

Ryan, I'm not sure where you got the copy of imap.cfc you are using, but the current version (1.0) does not have any comments at the top.

Here's a little more detail on locations.

<cfset this.sslenabled = 0 />
This goes in with the other cfset tags just after the opening cfcomponent tag.

<cfif isdefined("arguments.ssl")>
<cfset this.sslenabled = 1 />
</cfif>
These lines should go at the end of the init function, just before the closing cffunction tag.
Ryan

Ryan wrote on 01/09/08 9:49 PM

I got my imap.cfc from here: http://www.opensourcecf.com/CFOpenMail/imapcfc_view.cfm

Which appears to be completely different...

Anyway I used the other one and now I've got it working - awesome! But it seems very slow... When I call list() it appears to get all the messages in the account! How can that be usable? I have 1000's of messages in my gmail, don't most people?

thanks.

(Arg - I've tried to post this three times now and can't get past your captcha - you should try Wordpress - 0 spam without captchas)
Michael Sprague

Michael Sprague wrote on 01/09/08 10:49 PM

Sorry about the captcha. I need to switch that out for something. When WordPress reprograms everything in CF, I will switch. :-) For now, I can swap out the captcha for the built-in CF8 method - at some point.

For your list problem, the solution is posted above.

Run the count() function first to get the number of messages, then only retrieve the first X messages by using the list() function and passing in the message IDs.
Ryan

Ryan wrote on 01/09/08 11:13 PM

Sorry about the double post - I refreshed the page to see if you had responded, and it posted my comment again! (I could plug Wordpress again because it won't do that, but I won't...)

Ok - I didn't think the count() method would work, because it just returns a count, not message IDs. Now I see that the message IDs are just incrementing numbers, so you can just fetch numbers within the range of 1 to count(). The message ids are not unique to a message - this is not good! There is no way to ensure integrity this way... it may be a problem with the imap protocol, I don't know. But when you list out 100 messages, and the user clicks the delete icon next to message 55, you have no way of knowing if message 55 is still the same message it was when you loaded the list 2 minutes ago.
Michael Sprague

Michael Sprague wrote on 01/10/08 7:28 AM

Ryan - I understand your logic on this, but that is not how it works for us. I'll get you more details after I dig in further, but I just ran a test in our portal, and it does delete the correct message even when a new message has arrived since page load.
Ryan

Ryan wrote on 01/10/08 10:19 PM

Thanks for the replies Michael.

I don't think there will be a problem deleting after new messages have come in, as you said. But there will be if any of the *older* messages are changed, like moved to a different folder or deleted (by another imap session). Probably an unlikely senario, but still - even POP uses unique message identifiers to prevent things like this from happening.

Do you know if there is any documentation for imap.cfc? I'm having trouble, there aren't even hints in the argument tags.

For example, when I delete a message, what is the "value" argument for? Its required, but I don't know what to pass in.

Thanks.
Ryan

Ryan wrote on 01/10/08 10:24 PM

When I try to delete a message using the "delete" function, I get: "folder cannot contain messages". I don't get it, I'm not trying to delete a folder... at least I don't think thats what this method is for, since it takes a MessageNumber as one of the arguments.

Arg, Michael how do you use this thing without any documentation? Lots of trial and error? :-)
Kevin

Kevin wrote on 03/05/08 3:27 PM

I can't get this to work. It get the spinning wheel of death. I have double and triple checked by username and password but i don't get results nor an error page.

Has this happened to anyone else?
Kevin

Kevin wrote on 03/05/08 3:30 PM

I can't get this to work. It get the spinning wheel of death. I have double and triple checked by username and password but i don't get results nor an error page.

Has this happened to anyone else?
Mike Sprague

Mike Sprague wrote on 03/05/08 4:19 PM

I would suggest checking on the port in your firewall. 993 needs to be open.
Christian

Christian wrote on 04/08/08 9:32 AM

Does anyone know how to get a list all folders in an IMAP-account using imap.cfc? Have tried just about every method and seen every error message possible.

:)
Jason

Jason wrote on 04/08/08 10:15 AM

Christian,

After you init(), use the FolderList() method. This will return an account's folders in a query object.

Thanks,
Jason
Christian

Christian wrote on 04/08/08 10:31 AM

Thank you so much for replying Jason.

Tried that, but keep getting the Error: "folder cannot contain messages" on line 61 of imap.cfc when passing / as folder-argument to the function.

:)
Christian
Jason

Jason wrote on 04/08/08 10:42 AM

Christian, try submitting the folderlist() method without any arguments. This will return all folders.

Also, I believe that the folderlist() 'folder' argument should be a folder name, which likely explains the error you've described.

Write your comment



(it will not be displayed)





About Michael Sprague

Mike is a Web developer and manager from Central New York, specializing in ColdFusion, CSS, JavaScript, and Ajax development. More ...

Categories

Monthly Archives

Favorite Bloggers

Web Resources