【问题标题】:javamail mark gmail message as readjavamail将gmail邮件标记为已读
【发布时间】:2011-12-02 11:54:55
【问题描述】:

注意:在回答后添加: 谢谢..是的,我已经尝试将 Flag.SEEN 设置为 true 和 saveChanges.. 我还阅读了它读取的 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;
    }


}

【问题讨论】:

    标签: java jakarta-mail


    【解决方案1】:

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

    您可能认为这样做的方法是获取消息,将Flags.Flag.SEEN 标志设置为true,然后调用message.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 标志。

    【讨论】:

    • 好的,再次查看您的代码后,我注意到您使用的是 Folder.READ_WRITE,而我使用的是 READ_ONLY。一旦我改变它,它就会按预期工作。谢谢
    • 那么有没有办法让它表现得如此,除非明确标记为这样,否则消息不会被标记为 SEEN?我正在处理连接不良,有时在下载附件时连接断开。而且由于在发生这种情况时已经调用了 .getcontent,因此我需要确保它没有被标记为 UNSEEN。
    • 请注意,此方法需要下载整个消息以将其标记为已看到。
    • getContent() 不会将邮件标记为已读,如果它是 MIME 邮件,至少在我使用的 IMAP 中是这样。这不应该是公认的答案,请使用 Shloim 或 James Vornhagen 的答案。记住要测试所有可能的情况,因为每个 IMAP 实现都是不同的。
    【解决方案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);
    

    【讨论】:

    • 这将在不下载整个邮件的情况下完成。它仅适用于 imap
    • 这对我有用。只需要像这样切换到读写模式:emailFolder.open(Folder.READ_WRITE);
    【解决方案3】:

    您也可以考虑拥有一个public static int max_message_number,并在您阅读消息后立即将message[i].getMessageNumber(); 存储在其中。然后在阅读任何消息之前,只需检查max_message_number &lt; message[i].getmessageNumber()。如果为 true,则不打印此消息(因为它已被阅读)

    【讨论】:

      【解决方案4】:

      好吧,这篇文章很旧,但最简单的解决方案还没有发布。

      您正在访问消息。 message.setFlag(Flag.SEEN, true);

      【讨论】:

      • 这会更新本地副本,不会更新收件箱中的邮件。
      【解决方案5】:

      message.setFlag(Flag.SEEN,true) 给出“找不到符号” message.setFlag(Flags.Flag.SEEN,true) 看起来不错。

      【讨论】:

        【解决方案6】:

        如果您使用for循环来逐一阅读或检查邮件,代码可以如下标记gmail邮件为已读:

            Message[] unreadMessages = inbox.search(new FlagTerm(new Flags(Flag.SEEN), false));
                    for (int q = 0; q < unreadMessages.length; q++) {
        
                      unreadMessages[q].setFlag(Flag.SEEN, true);
        
                    }
        

        这段代码的作用是让它一个一个地不被读取。

        而且文件夹/收件箱也需要是 READ_WRITE,而不是 READ_ONLY:

        folder.open(Folder.READ_WRITE);
        

        【讨论】:

        • For 循环太贵了。服务器可以在一个命令中处理它:folder.setFlags(unreadMessages, new Flags(Flags.Flag.SEEN), true);
        【解决方案7】:

        最简单的方法是设置要读取或写入的文件夹。像这样的意思...

            Folder inbox = null;
            inbox.open(Folder.READ_WRITE);      
        

        文件夹类应该被导入。

        【讨论】:

          【解决方案8】:
          for (Message message : messages) {
                              message.setFlag(Flags.Flag.SEEN,true);
                          }
          

          更改下面的行

          folder.open(Folder.READ_ONLY);

          到此

          folder.open(Folder.READ_WRITE);

          【讨论】:

            【解决方案9】:

            你也可以试试

            前往 gmail 设置 > 转发和 POP/IMAP

            使用 POP 访问邮件时的下拉菜单中 选择将 Gmail 的副本标记为已读并保存更改

            【讨论】:

              猜你喜欢
              • 2015-01-15
              • 1970-01-01
              • 1970-01-01
              • 2011-01-12
              • 1970-01-01
              • 2015-10-08
              • 2016-07-30
              • 2013-02-02
              • 2014-12-18
              相关资源
              最近更新 更多