JavaMail按ReceivedDate搜索,无法精确到秒?

10

在IMAP中,消息编号是基于消息被放置到文件夹中的时间(即文件夹中的第一条消息为1,第二条为2等)。然而,这种排序方式并不考虑消息的接收日期。我关心的是那些早于文件夹中第一条消息的消息,也就是用户手动移动到文件夹中的消息(而不是由系统接收时移动到文件夹中的消息)。

我不能只获取每个消息的接收日期,因为这非常低效。

认为我可以使用JavaMail搜索来获取所有接收日期早于第一条消息接收日期的消息(同样地,然后进行搜索以获取所有接收日期晚于第一条消息接收日期的消息…虽然这将是很多条消息,但我只需要处理所有较旧的消息,只需要处理其中的一些较新的消息(通过处理,我指下载其标题)。

然而,在我使用搜索时,它似乎无法正常工作。

        Message[] messages = csqFolder.getMessages();           

        if (messages != null && messages.length > 0) {

            Date receivedDate = messages[0].getReceivedDate();
            log.trace("Message 1 receivedDate: <" + receivedDate.toString() + ">");
            SearchTerm msgsOlderThanOETFirst = 
                new ReceivedDateTerm(DateTerm.LT, receivedDate);

            SearchTerm msgsNewerThanFirst = 
                new ReceivedDateTerm(DateTerm.GT, receivedDate);

            Message[] oldMsgs = csqFolder.search(msgsOlderThanOETFirst, messages);
            log.trace("Size of oldMsgs: <" + oldMsgs.length + ">");
            Message[] newMsgs = csqFolder.search(msgsNewerThanFirst, messages);
            log.trace("Size of newMsgs: <" + newMsgs.length + ">");

然而,当我运行这些搜索时,似乎没有给出正确的结果。

在一个包含 8 条消息的文件夹中,其中有 7 条消息的接收日期时间都在 8 月 5 日下午 12:00 左右,但是该文件夹中的第一条消息是在 8 月 5 日下午 4:00 的,我们会看到以下内容:

Message 1 receivedDate: <Fri Aug 05 16:46:57 CDT 2011>
Size of oldMsgs: <0>
Size of newMsgs: <7>
然而,剩下的七条信息全部比第一条信息旧... 它们都应该在oldMsgs中。
也就是说,如果我将前一天(8月4日)的一条消息放入文件夹中,那么搜索将正确地工作... 只针对这一条消息。就好像搜索只能按天计算,而不能精确到秒...
需要注意的是,在术语msgsOlderThanOETFirst中,我最初使用了LE(因此得名),但是这会导致上述结果翻转--所有消息都将被找到位于oldMsgs中。
有人可以确认这种行为是否正确,如果正确,这是否指向Java中的一个错误?
我尝试查看搜索的源代码,但我想我得到的是命令行版本而不是javamail包使用的版本...
我正在使用带有SP1的MS Exchange 2007和JavaMail 1.4.3。
感谢任何建议。
更新:我不认为我的比较器顺序读取有误。请参阅以下主题中给出的答案:java imap fetch messages since a date 假设我们使用该答案,并且我们将我们的范围从2011年7月15日至2011年9月15日。然后,我们让搜索将一条消息与给定日期8/4/2011进行比较。然后我们会得到以下结果:
                                              8/4/2011  <     9/15/2011
SearchTerm olderThen = new ReceivedDateTerm(ComparisonTerm.LT, someFutureDate);
SearchTerm newerThen = new ReceivedDateTerm(ComparisonTerm.GT, somePastDate);
                                              8/4/2011  >     7/15/2011

这两种情况下都会评估为真,这是我们期望的,因为日期在所需范围内。

同样,我的代码如下:

    SearchTerm msgsOlderThanOETFirst =    8/4/2011  < 8/5/2011
            new ReceivedDateTerm(DateTerm.LT, receivedDate); --> TRUE
    SearchTerm msgsNewerThanFirst =       8/4/2011  > 8/5/2011
            new ReceivedDateTerm(DateTerm.GT, receivedDate); --> FALSE
上述TRUE和FALSE的评估结果是我期望和将要得到的。但是,如果我们考虑一个给定的消息在2011年8月5日12:00:00,我们会得到以下结果:
    SearchTerm msgsOlderThanOETFirst =    8/5/2011 12:00:00  < 8/5/2011 16:46:00
            new ReceivedDateTerm(DateTerm.LT, receivedDate); --> TRUE?
    SearchTerm msgsNewerThanFirst =       8/4/2011 12:00:00  > 8/5/2011 16:46:00
            new ReceivedDateTerm(DateTerm.GT, receivedDate); --> FALSE?

不过,我们没有得到期望的结果,相反我们得到了反向的结果……此时很容易陷入思维困境,但是我已经多次核对过。JavaMail是否存在问题,还是我完全搞错了?如果是后者,请纠正我的困惑!


你可以尝试使用JavaMail API的不同实现,其源代码可用于调试问题,例如http://jarvana.com/jarvana/archive-details/org/apache/geronimo/specs/geronimo-javamail_1.4_spec/1.7.1/geronimo-javamail_1.4_spec-1.7.1.jar。但是不保证不同实现之间的行为相同。 - bstick12
是的,那是个打字错误。已经修复了。目前我倾向于认为这是一个 bug,如果是的话,尝试调试并不值得。但如果 JavaMail 的官方版本中有针对此问题的修复,我会使用它的。 - Jon
你能提供一个输出,其中put显示Message[]中每个消息的接收日期吗? - bstick12
我确实有这样的输出。在我的7条消息测试中,它显示我期望在OldMsg中的所有消息实际上都在newMsgs中。显然,oldMsgs是空的。你具体想要什么?由于示例中的消息已被删除,我无法再给你那个精确的输出了,除非创建一个新的测试。 - Jon
你能循环遍历消息数组并记录数组中每个消息的receivedDate吗? - bstick12
显示剩余2条评论
1个回答

8
根据JM开发者Bill Shannon的说法,这是IMAP协议的限制:
from    Bill Shannon 
to  Jonathan Hanson 
cc  javamail_ww@oracle.com
date    Wed, Aug 10, 2011 at 11:55 AM
subject Re: Bug with searching by ReceivedDateTerms
mailed-by   oracle.com
    Important mainly because of your interaction with messages in the conversation.

hide details 11:55 AM (16 minutes ago)

The searching is being done by the IMAP server, and you're running into a limitation of the IMAP protocol.

1
限制在于 IMAP SEARCH BEFORE 只接受日期(不带时间),而不是日期+时间,对吧?(引用 RFC 3501 的话:“BEFORE <date> - 内部日期(忽略时间和时区)早于指定日期的邮件。”) - David
1
这个问题有什么解决方案吗?我真的想根据时间过滤邮件,我只想要在最近2分钟内收到的邮件,怎么做呢? - Paresh
解决方案是不要使用IMAP搜索,它很糟糕。最好的解决方案是更新IMAP协议,否则使用不同的协议(如MAPI-在JavaMail中不可用)。如果必须按原样使用IMAP,则最好在理解IMAP文件夹作为FIFO队列的基础上工作。保持消息的内存映射,并每2分钟跟踪新消息。 - Jon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接