javamail 将 gmail 邮件标记为已读

2022-09-01 07:09:33

注意:回答后添加:谢谢.是的,我试过了 Flag.SEEN to true 并保存更改..我也读过getContent标记它读。我尝试在循环访问消息的for语句中使用它。但是,无论如何,在下一个循环中,我还是从文件夹中再次收到了消息。我假设该文件夹是实时的,因此抓取内容,然后使用过滤器从文件夹中再次抓取邮件以使其看不到任何内容应该有效,但我仍然收到相同的邮件。我可以尝试关闭文件夹并重新打开作为测试,以查看它是否被标记。此外,如果我转到我的客户端并单击该消息,那么即使在循环中,我的代码也会停止看到它,所以我希望在代码中执行相同的操作。

原创:我正在使用javamail从gmail帐户获取电子邮件,它工作得很好,当我收到我想将其标记为已读的消息时,任何人都可以给我一些指导吗?这是我当前的代码:

    Properties props = System.getProperties();
    props.setProperty("mail.store.protocol", "imaps");
    try {
        Session session = Session.getDefaultInstance(props, null);
        Store store = session.getStore("imaps");

        store.connect("imap.gmail.com", eUserName, ePassWord);
        // Get folder
        Folder folder = store.getFolder("INBOX");
        if (folder == null || !folder.exists()) {
            return null;
        }
        folder.open(Folder.READ_ONLY);

        // Only pull unread
        FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
        Message messages[]; // = folder.search(ft);

        for(int x = 0; x < timeOutInSeconds; x++) {
            log.reportMessage("looking for emails");
            try {
                folder.getMessages();
                messages = folder.search(ft);

                if (messages.length > 0) {
                    for (Message message : messages) {
                        //log.reportMessage("found message: should not see again, marking read");
                        // want to mark as read

                    }
                }
                Thread.sleep(1000);
            }
            catch(Exception ex) {

            }
        }

        // Close connection
        folder.close(false);
        store.close();
        return null;

    }
    catch (NoSuchProviderException ex) {

        return null;
    }
    catch (MessagingException ex) {

        return null;
    }


}

答案 1

首先,如果您使用的是 POP3 服务器,则无法将邮件标记为已读 - POP3 协议不支持此功能。但是,IMAP v4 协议可以。

您可能会认为执行此操作的方法是获取消息,将标志设置为 true,然后调用 。奇怪的是,事实并非如此。Flags.Flag.SEENmessage.saveChanges()

相反,JavaMail API 设计规范,第 4 章“标志类”一节指出,在检索消息内容时隐式设置了标志。因此,要将消息标记为已读,可以使用以下代码:SEEN

myImapFolder.open(Folder.READ_WRITE);
myImapFolder.getMessage(myMsgID).getContent();
myImapFolder.close(false);

或者另一种方法是使用MimeMessage复制构造函数,即:

MimeMessage source = (MimeMessage) folder.getMessage(1)
MimeMessage copy = new MimeMessage(source);

构造副本时,将为源引用的消息隐式设置 seen 标志。


答案 2

一个班轮可以在不下载整个消息的情况下完成此操作:

单条消息:

folder.setFlags(new Message[] {message}, new Flags(Flags.Flag.SEEN), true);

所有消息:

folder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);

调用或创建副本的其他方法会导致客户端下载整个消息,并造成巨大的性能损失。getContent()new MimeMessage(original)

请注意,必须打开收件箱才能READ_WRITE:

folder.open(Folder.READ_WRITE);

推荐