Figuring out how many mails are in a POP account

This post is more than 2 years old.

Edit 2/20/2013: Be sure to see Karl's comment! I got an interesting question earlier this week. A reader was using cfpop to retrieve email information. They had built a paging system by using getHeadersOnly. This returns a 'slimmer' query where email bodies are not included in the result. He then paged through the query and fetched the bodies 10 at a time. (Do I need to demo that? Let me know and I'll do another blog entry.) This worked fine until the email account got overloaded. Eventually even the "quicker" getHeadersOnly operation was taking forever. He ask - is there some way to get just the total number of messages in a mailbox?

I double checked the documentation for cfpop and didn't see any particular support for this operation. On a whim I tried the following:

<cfpop server="Mail.colts.com" action="getHeaderOnly" username="raycamden@colts.com" password="icodephpinthecloset" name="mail" maxrows=1 startrow=999 >

This returned:

The start row 999 is greater than the total number of messages 5.

So cfpop definitely was able to get the total number of messages, but I saw no way to get that myself. I could have wrapped the call in a try/catch and parsed the error, but that just felt dirty to me.

I did some digging into the javax.mail package which ColdFusion uses under the hood for it's mail support. It was a bit confusing at first, but this article helped a bit and formed the basis for my code. Basically, POP support entails creating a Mail Session (not the same as a ColdFusion session!), a mail store, and finally grabbing the inbox folder. The Folder object contains a method that returns a message count. It took me a good hour or two to figure this out (boy do I appreciate how easy ColdFusion makes things!) but I was able to get it down to a few lines of code:

<cfset props = createObject("java","java.lang.System").getProperties()> <cfset msession = createObject("java", "javax.mail.Session")> <cfset m2 = msession.getDefaultInstance(props)> <cfset store = m2.getStore("pop3")> <cfset store.connect("Mail.colts.com","raycamden@colts.com","isecretlywritephp")> <cfset df = store.getFolder("INBOX")> <cfset df.open(df.READ_ONLY)> <cfdump var="#df.getMessageCount()#">

The main line you would care about is the connet operation. Note the server, username, and password (yes, it's fake). The df variable is my folder object. You can do more with it then just getting a count obviously, but actually getting mail would be simpler with cfpop. If you actually used this in production you would probably want to turn it into a UDF.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Michael Hnat posted on 5/20/2009 at 5:10 PM

Very interesting! Thx. Maybe there is also a way to see if an email has an attachment without getting the full body information.

Best,
Michi

Comment 2 by Seth posted on 5/20/2009 at 5:14 PM

You can do it using IMAP as well, not sure who to credit for this code: http://rafb.net/p/IX15UV86....

Comment 3 by Andy Sandefer posted on 5/20/2009 at 8:19 PM

@Ray
This was an interesting read but I have one question. Does the getMessageCount() method take into consideration the number of messages held in nested subfolders within the folder that you're doing the count on? So for instance if I have an e-mail folder named clients and then underneath that I have a folder for each client but I want the count of total client e-mails does the method provide recursion?
I can't figure this out by reading Sun's docs so I'll probably just have to test it sometime.
There is a HOLDS_FOLDERS attribute (constant field) which can be summoned to figure out if a folder can hold other folders but I've never tried to use it.
Just curious - thanks for the cool post!

Comment 4 by Raymond Camden posted on 5/20/2009 at 8:23 PM

I have no idea Andy. I'd love it if someone could test with a subfolder. I'd also be curious to see if cfpop would return the subfolder contents. If not, it doesn't matter. It was my impression cfpop was just getting the root folder.

Comment 5 by Andy Sandefer posted on 5/20/2009 at 8:26 PM

I have a mail type project coming up so I'll make a note to share my java mail api findings with the rest of the group (I just love littering your blog ya know).

Comment 6 by Mamdoh Alhabeeb posted on 5/20/2009 at 8:27 PM

Can't the reader use the "recordcount" to get the total number of messages in a mailbox as the following?

<CFPOP server="Mail.colts.com"
action="getHeaderOnly"
username="raycamden@colts.com"
password="icodephpinthecloset"
name="mail">

<CFSET Totalcount = mail.recordcount/>

Comment 7 by Raymond Camden posted on 5/20/2009 at 8:28 PM

Mamdoh, please reread the entry a bit closer. Yes, he can, but the process of getting the headers was taking too long. If you do maxrows=10, the recordcount will be 10, not the 'real' count on the mail server.

Comment 8 by Connie DeCinko posted on 5/22/2009 at 12:05 AM

I've used a process very similar to what was first mentioned in order to get the number of unread messages in a mail account. Same problem... if the user's inbox is overloaded with messages, it takes way too long to get the count. Using your method, could you get the number of unread/new messages?

Comment 9 by Raymond Camden posted on 5/22/2009 at 12:23 AM

Yep, it's one more method in the Folder object:

http://java.sun.com/product...

Comment 10 by Connie DeCinko posted on 5/22/2009 at 1:04 AM

No joy. getUnreadMessageCount() gives me the number of total messages and getNewMessageCount() gives me zero. Perhaps this does not work with our version of iMail.

Comment 11 by Karl Wagenfuehr posted on 2/20/2013 at 9:14 AM

An old thread, I know, but I found it very useful today, except for one thing: you have to close off the mail session, or else any subsequent cfpop attempts won't work! The link to the java article is dead (shouldn't a UNIVERSAL record locator be forever?), but I found what I needed somewhere else (and yes, once you know it's duh obvious -- isn't hindsight great?); put this at the end of the above code:
<cfset df.close(false)>

Comment 12 by Raymond Camden posted on 2/20/2013 at 9:03 PM

Thank you for sharing that Karl. I felt your comment was important enough for me to update the entry to point it out.

Comment 13 (In reply to #6) by JOHN JORDAN posted on 11/23/2016 at 9:45 AM

Of course It will work, but It will only work when you're fetching all the email from the inbox. What if you're fetching only 30 emails.? Well mail.recordcount will return 30 only.

Comment 14 by Michael D Glassberg posted on 2/7/2018 at 3:33 AM

Shouldn't you close everything?

<cfset df.close(true)="">
<cfset store.close()="">

Comment 15 (In reply to #14) by Raymond Camden posted on 2/7/2018 at 1:22 PM

Karl's comment mentions closing df, but that wouldn't hurt too.