I blogged earlier about an issue with cfpop when doing a "getall" on mail. This issue can be fixed by getting just the headers and then looping over and grabbing each message. I decided to use the mail message UID feature to get the individual email message since I figured this was safer than just using the messages number index.
However, the speed was incredibly slow. Michael Dinowitz alerted me to an old bug that explains the problem - when you fetch a message by UID, CF actually grabs all the messages and then parses each message to find the UID.
What I'm curious about, and I'll need to test to find out, is if new emails arrive, do they always end up at the "end" of the stack? If so, than it is safe to get mail message #1, read it, and delete it, and then fetch #1 again, which would have been the old #2.
Archived Comments
Just a bit of clarification. In CF 5, the UID was a unique identifier generated by the mail server for each message. In post.office, the UID happened to the the file name. Other mail servers may differ. In CFMX (version 1 on), the UID was changed to be the messageid of the message. This is a header value that does not always exist (is not required by the RFC).
When CFPOP retireves a message, it parses the message, gets the header and returns chunks of it as CFPOP variables. When getting a message by UID in CFMX, it has to parse the message to find the messageid that matches the UID that is sent in.
This was identified as a bug late in the redsky cycle and there is a tech note mentioning that a fix was already placed into the next edition of CF. If you want, I can look up the tech note.
As for message placement, a new message is added to the 'bottom' of the mail 'stack' so the more messages in a directory, the slower it will be to get a message by UID in CFMX.
Michael, does that mean it is NOT safe to read 1, delete 1 and assume you are deleting the same msg you read? I thought that if a msg came in, it would be number N+1 where N is the old # of messages.
The first message the system received in real time is listed as message 1. The second is message 2. Even if the second is dated a year earlier, the mail server will still set it to message 2.
When using the message number method and no one else is getting messages as your doing it, then there is no problem with getting message 1, deleting message 1. The problem does come in if you plan to get and delete multiple messages at a time where they are non-sequential. Deleting message 1,2,3,5 will have to be done either by deleting message 5 first, then 3, then 2, then 1 OR by deleting all of the numbers at once (it's possible in the CFPOP tag).
Deleting by message number is dangerous but if done correctly, it can be safe. Deleting by UID is much safer, but is currently not a viable option in CFMX. I'd suggest using the CFX_Pop3 tag for now and once the next fix from MM comes out (standalone or full release), then use that.
If you need, I've got a TON of code for mail processing as I do it for my lists, for my archives of other lists, for my personal spam catcher, etc.
Yea, I get the idea about being careful how I delete, it is the same as working w/ an array. In this case, I'm the only "reader" of the pop account, so I guess I'm ok with using cfpop.
I thought I had gotten that fix in to 6.1 but it went in right after redsky shipped. Sorry about that. Here are the details of what will change next time:
Fix bug 52970: CFPOP uid field does not match CF5.
The 'uid' column had been altered in CFMX and the UID being returned from CFPOP is actually the Message-ID of the message, not the UID. In earlier versions of CF, the CFPOP tag would return the UID of the message. This is by far superior to the use of the message ID.
Added a new column in the query returned by CFPOP: MessageID.
This is the value of the Message-ID header in each message. Any CFMX user that was depending on uid to contain this value can now use this column.
Tom - a few questions:
1) Are you saying that the fix didn't make 6.1, and is also not available as a hotfix? Any way we can get a hotfix out for it?
2) Your fix seems wrong though - while it does add a new column to the query returned, my real need for a UID was when I called "get one message" or "delete one message", having the new column does not help if I can't use the value as well when calling cfpop. Does that make sense?
1. There is currently no hot fix for this. I don't know if we can get one out, I mucked with quite a but of the POP code to make it go faster. The 'bug' fix doesn't give you more than performance, as the current implementation should work correctly, just slowly. :-(
2. The UID in the fixed code is now the (correct) value returned by the POP server via the UIDL POP command. I just added the MessageID field in the return query as a help for those you might have coded their CFML to depend on it. You will be able to use this value to get/delete messages in an effcient way.
I hope this clears it up.