Connecting to Gmail using ColdFusion

ColdFusion , Default , Web Development Add comments

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.

48 responses to “Connecting to Gmail using ColdFusion”

  1. Brian Says:
    Great article, thanks for sharing this with us.
  2. David Says:
    I am interested in your idea for passing in multiple message IDs...can you share the code for this?
  3. Mike Says:
    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#">
  4. Ryan Says:
    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
  5. Michael Sprague Says:
    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.
  6. Ryan Says:
    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)
  7. Michael Sprague Says:
    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.
  8. Ryan Says:
    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.
  9. Michael Sprague Says:
    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.
  10. Ryan Says:
    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.
  11. Ryan Says:
    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? :-)
  12. Kevin Says:
    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?
  13. Kevin Says:
    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?
  14. Mike Sprague Says:
    I would suggest checking on the port in your firewall. 993 needs to be open.
  15. Christian Says:
    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.

    :)
  16. Jason Says:
    Christian,

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

    Thanks,
    Jason
  17. Christian Says:
    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
  18. Jason Says:
    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.
  19. peters Says:
    I cannot make it work, do you provide $upport ?
    I am tired to solve this problem and need a solid solution to replace de CFPOP. What are the conditions ?
  20. Jason Says:
    Peters - what specifically isn't working? Could you provide snippets / error messages?
  21. Kashif Says:
    Is there a way to fetch address book or contact list from gmail account? Anyone would like to comment on this. Thanks
  22. Jason Says:
    Kashif - take a look at the Google Contacts Data API at http://code.google.com/apis/contacts/

    Thanks,
    Jason
  23. Sierra Says:
    Hi Michael,
    Isn't it right that this would be necessary to add to line 15?

    <cfargument name="ssl" required="No">

    Also, your code mod above is returning the first ten messages in my inbox (from five years ago), not the ten most recent.
    Thanks for making this post! It's already very useful for me.
  24. Sierra Says:
    Try this for the most recent 10:

    <cfscript>
          imapCFC = CreateObject("component","imap.imap");
       imapInit = imapCFC.Init("#mail_accts[i]["email"]#","#mail_accts[i]["pw"]#","imap.gmail.com",993,15,1);
          
          foldername = "Inbox";
          limit = "10";
          msgIDs = "";

          // Get a count of messages in the folder
          msgcount = imapCFC.count(foldername);

          // Determine how many messages to get
          if (msgcount LTE limit)
             from=1;
          else
             from=msgcount - limit;

          // Build list of message ids
          for(i=from;i lte msgcount;i=i+1)
             msgIDs = ListAppend(msgIDs,i);
          
          // Get headers for message id list
          msgs = imapCFC.list(foldername,msgIDs);
       </cfscript>

    <!--- Return a query of messages --->
    <cfdump var="#msgs#" />
  25. Sierra Says:
    Sorry, I've got i in there for two different loop indices. You get the idea, tho.
  26. Thomas Says:
    I am getting the following error

    "No provider for imaps "

    Any help will be appreciated.
  27. Michael Sprague Says:
    This is not an error that is being displayed by imap.cfc. It must be coming from something external to the CFC. Check one of the following...

    1. IMAP is enabled in your Gmail account settings.
    2. The port you are using for IMAP is not blocked by your network or local firewall.

    Also, what version of CF are you running. This has only been tested with 7 and 8. I supposed it is possible that the underlying java libraries of older versions do not support imaps.
  28. Thomas Says:
    I am using coldfusion MX.

    The site is hosted by ready hosting so not sure if they are blocking a port.

    IMAP is enabled on my account
  29. Thomas Rivera Says:
    My hosting provider says port 993 is blocked due to security reasons :( Is there anyway around this?
  30. Michael Sprague Says:
    Google runs their IMAP on port 993, so I don't think there is any way around it other than asking your hosting company to enable it for your server.
  31. Amir Says:
    I get the same messager "No provider for imaps "
    ColdFusion 7 is running on localhost with no changes to the default setting. Firewall is off!

    Any suggestion?
  32. Michael Sprague Says:
    Two things to check...

    1. Make sure IMAP is enabled in your Gmail account, under Settings.

    2. As an experiment, try setting up a mail client on the server and checking your Gmail using IMAP. If that doesn't work either, then something on your network is blocking the IMAP port or server.

    One additional note... soon-to-be released ColdFusion 9 has a CFIMAP tag and can be used to connect to Gmail.
  33. Amir Says:
    1. IMAP is enabled in gmail. I can pick up mails using outlook express and IMAP.

    2.I dont understand what you mean by setting up a mail client on the server. Is this what we are trying to do in the first place?

    Network should be fine since outlook works from the same server(my laptop).

    Another thing, when I this.sslenabled=0, I never get any response, firefox shows "loading..." at page title forever. I get the error message "No provider for imaps " when I this.sslenabled=1 immediately.
  34. Ryan Stille Says:
    And don't forget, Railo and BlueDragon support cfimap already (and have for quite some time).
  35. Michael Sprague Says:
    @Amir - What type of server are you running this on? Windows/Linux/Mac? Are you able to remote into it and run a mail client at the desktop? This is the test I was referring to. If the mail client can connect from the server's desktop, then ColdFusion should be able to as well.

    We have this CFC running, as above, on several Windows servers with CF7 or CF8. I have not tested it in other environments, so others in this comment thread may have to step in and let you know if that works. It SHOULD work, since it is just Java, but it has not been tested.
  36. anonymous user Says:
    Well this is very interesting indeed.Would love to read a little more of this. Great post. Thanks for the heads-up…This blog was very informative and knowledgeable
  37. Amir Says:
    also see:
    http://www.opensourcecf.com/1/2006/12/ImapCFC-Update.cfm
  38. Andrew Says:
    What's the folder name for "Sent"? I can get the Inbox to pull messages, but I can't get into anything else.
  39. anonymous user Says:
    I needed this info thanks mate

    Regards
  40. Dev Says:
    Guys,

    I am having a problem when I use getFolderlist(),
    It goes on well until the getFolder() method is called from openFolder(), It gives me an error :

    The getFolder method was not found.
    Either there are no methods with the specified method name and argument types, or the getFolder method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that matched the provided arguments. If this is a Java object and you verified that the method exists, you may need to use the javacast function to reduce ambiguity.

    Please Help!!
  41. Jason Says:
    If you cfdump the arguments.objStore variable in OpenFolder() what do you see? Is the getFolder method available?

    If the getFolder() method isn't available you may be having problems with your objStore. Also, what is the name of the folder you're trying to open? Any special characters?
  42. Nirav Says:
    I just want to load only unread mail in inbox with the use on 'listMessages' Method, without loading all mail of inbox.

    Any solution??
  43. Jason Says:
    Nirav,

    I think you'll want to run a query of queries against the result set from list() as follows:

    <cfset messages = imapObj.list() />

    <cfquery name="unread" dbtype="query">
    SELECT *
    FROM messages
    WHERE seen = 0
    </cfquery>
  44. Nirav Says:
    Thanks Jason
    But it's take more time when there are thousands of mails in the account and only few of them are unread. I don't want to load all read mails.


    And also I can't find the method for listing all folders, such as 'listAllFolders' method of cfimap tag.
  45. Mike Says:
    Nirav - If you just want the new messages, you might want to try using Gmail Inbox Feed instead of IMAP. It's very fast and can be retrieved with the cffeed tag.

    http://code.google.com/apis/gmail/docs/inbox_feed.html
  46. Pat Says:
    can someone help me?? I keep getting a Connection timed out: connect; nested exception is: java.net.ConnectException: Connection timed out: connect

    even try the pop3 but getting the same so Im assuming it must be my server?
  47. Jason Says:
    Pat, are you sure your connection information (server, username, password, and port are correct? You can also try increasing your timeout. It's the 5th argument in the init(). If it's an SSL connection, make sure the sixth argument is 1.
  48. J V SUBRAMANYAM Says:
    The Imap.cfc for retriving the mails from IMAP mail account is taking more time if the inbox contains thousands of mails.
    Any method is there in the imap.cfc for retriving only un read mail headers
    How to reduce the time taken for reading the mail headers using Imap.cfc

    Thanking you

Leave a Reply

Leave this field empty:



Powered by Mango Blog. Design and Icons by N.Design Studio