草庐IT

JavaMail : Keeping IMAPFolder. 闲置()还活着

coder 2023-08-30 原文

我正在制作一个需要监视 Gmail 帐户是否有新邮件的程序,为了尽快收到它们,我正在使用 JavaMail 的闲置功能。这是我用来调用 folder.idle() 的线程中的代码片段:

//Run method that waits for idle input. If an exception occurs, end the thread's life.
public void run() {

    IMAPFolder folder = null;

            try {
                folder = getFolder();
                while(true)
                {
                  //If connection has been lost, attempt to restore it
                  if (!folder.isOpen())
                      folder = getFolder();
                  //Wait until something happens in inbox
                  folder.idle(true);
                  //Notify controller of event
                  cont.inboxEventOccured();
                }
            }
            catch (Exception ex) {
                ex.printStackTrace();
            }
             System.out.println("MailIdleWaiter thread ending.");
}

getFolder() 方法主要是打开与 IMAP 服务器的连接并打开收件箱。

这工作了一段时间,但在 10 分钟左右后它停止获取更新(没有抛出异常)。

我正在寻找保持连接有效的建议。我是否需要第二个线程,其唯一作用是每 10 分钟 hibernate 并更新 idle() 线程,还是有更简单/更好的方法?

提前致谢。

最佳答案

一个常见的错误是假设 IDLE 命令会无限期地发布更新。然而,RFC 2177 ,它定义了 IDLE 扩展状态:

The server MAY consider a client inactive if it has an IDLE command running, and if such a server has an inactivity timeout it MAY log the client off implicitly at the end of its timeout period. Because of that, clients using IDLE are advised to terminate the IDLE and re-issue it at least every 29 minutes to avoid being logged off. This still allows a client to receive immediate mailbox updates even though it need only "poll" at half hour intervals.

特别是 GMail,超时时间要短得多,如您所说,大约 10 分钟。

我们只需要每 9 分钟左右重新发出一次 IDLE 命令,它就可以工作了。 javax.mail API 无法为 IDLE 命令设置超时,因此您需要第二个线程来解决这个问题。

第一种方法是让第二个线程中断第一个线程,处理异常并忽略它。然而,这将不允许以干净的方式关闭线程,所以我不会推荐它。一种更简洁的方法是让第二个线程向服务器发出 NOOP 命令。这根本不执行任何操作,但足以让 IDLE 中止并重新发布。

我在这里提供了一些代码来做到这一点:

public void startListening(IMAPFolder imapFolder) {
    // We need to create a new thread to keep alive the connection
    Thread t = new Thread(
        new KeepAliveRunnable(imapFolder), "IdleConnectionKeepAlive"
    );

    t.start();
    
    while (!Thread.interrupted()) {
        LOGGER.debug("Starting IDLE");
        try {
            imapFolder.idle();
        } catch (MessagingException e) {
            LOGGER.warn("Messaging exception during IDLE", e);
            throw new RuntimeException(e);
        }
    }
    
    // Shutdown keep alive thread
    if (t.isAlive()) {
        t.interrupt();
    }
}

/**
 * Runnable used to keep alive the connection to the IMAP server
 * 
 * @author Juan Martín Sotuyo Dodero <jmsotuyo@monits.com>
 */
private static class KeepAliveRunnable implements Runnable {

    private static final long KEEP_ALIVE_FREQ = 300000; // 5 minutes

    private IMAPFolder folder;

    public KeepAliveRunnable(IMAPFolder folder) {
        this.folder = folder;
    }

    @Override
    public void run() {
        while (!Thread.interrupted()) {
            try {
                Thread.sleep(KEEP_ALIVE_FREQ);
                
                // Perform a NOOP just to keep alive the connection
                LOGGER.debug("Performing a NOOP to keep alvie the connection");
                folder.doCommand(new IMAPFolder.ProtocolCommand() {
                    public Object doCommand(IMAPProtocol p)
                            throws ProtocolException {
                        p.simpleCommand("NOOP", null);
                        return null;
                    }
                });
            } catch (InterruptedException e) {
                // Ignore, just aborting the thread...
            } catch (MessagingException e) {
                // Shouldn't really happen...
                LOGGER.warn("Unexpected exception while keeping alive the IDLE connection", e);
            }
        }
    }
}

关于JavaMail : Keeping IMAPFolder. 闲置()还活着,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4155412/

有关JavaMail : Keeping IMAPFolder. 闲置()还活着的更多相关文章

  1. c# - 有 .NET 的 Relaxer 吗? Relaxer 还活着吗? RelaxNG 可行吗? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭5年前。Improvethisquestion我读到了Relaxer,它可以将.RNG编译为Java类。B但是网站,http://www.relaxer.org/,死了。Q1:Relaxer还活着吗?是真的吗,有用吗?从.RNG生成Java类是否合理?Q2:有.NET的Relaxer吗?是否有从RelaxNG模式生成C#类的工具?Q3:有没有针对Javascript的Relaxer?然后,最后Q4:RelaxNG

  2. http - 如何让 Go 的 http.Server 闲置一段时间后退出? - 2

    我正在使用标准库net/http包在Go中编写一个Web服务器,该包利用systemd套接字激活。我有基本的工作原理,这样服务器在第一次连接到监听套接字时启动,并且我可以在发出信号时执行正常关闭(即systemctlstop将在没有切断事件请求)。我希望服务器在闲置一段时间后自动退出。类似于以下内容:当最后一个事件请求完成时,启动一个计时器,比如30秒。如果在此期间有任何新请求到达,则停止计时器。如果计时器到期,则执行正常关机。我们的想法是释放服务器正在使用的资源,因为我们知道systemd会在新客户端出现时再次启动我们。我不确定的是第(1)和(2)部分。理想情况下,我想要一个不涉及修

  3. windows - 如果闲置则自动退出批处理的命令? - 2

    我想知道是否有一个命令可以在批处理文件单独放置一定秒数后自动退出。我制作了一个类似于发现的小程序here.我使用的大部分编码都显示在页面上,但它基本上会询问您要访问哪个网站,然后选择其中一个选项会打开一个包含所需页面的浏览器窗口。但是,在选择列出的站点之一后,程序会显示退出或返回顶部的选项。这是我通常忘记它的地方,直到我关闭我正在看的任何东西,并且该批处理仍在后台打开。那么有没有办法设置自动退出计时器而不打扰用户,并且不限制返回并选择另一个选项的能力?谢谢! 最佳答案 你可以使用choice命令,而不是set/pz是一个自动选项,您

  4. python - 有时脚本闲置,需要我按 RETURN 才能解锁它们 - Python - 2

    这已经发生了很多次,并且无法以任何方式解释这种行为。我经常为一些快速任务编写快速Python脚本,这些任务通常是使用Django的ORM进行行迭代。例子:fromcore.modelsimportMyModelITEM_IDS=[...]forindex,item_idinenumerate(ITEM_IDS):printindexifMyModel.objects.filter(serial=item_id).count():do_something()printindex,item_id有时脚本会无限期地停止在其中一个迭代中,按RETURN快速恢复交互!!!编辑:这发生在Windo

  5. c++ - 我的 C 程序为钩子(Hook)提供了一个回调函数。我怎样才能让它活着,不笨拙? - 2

    目前,我正在生成一个带有操作系统库函数(Windows.h)的消息框,它神奇地让我的程序保持事件状态并响应对回调函数的调用。有什么替代方法可以让程序默默地永远运行?捕获“Ctrl-c”或SIGINT并随后调用RemoveHook()以干净退出会很好,但不是必需的。HOOKmy_hook;CALLBACKmy_callback_fn(){...}intmain(){my_hook=SetHook(my_callback_fn);MessageBox("PressOKtostop.");//Thisisbad.RemoveHook(my_hook);return0;}

  6. java - 闲置仪表 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:javacpuusagemonitoring我正在尝试用Java编写一个程序,当计算机在一段时间内未处于Activity状态(例如CPU使用率)时,它可以关闭您的计算机。我编写了一个程序,可以在一段时间后关闭您的电脑(windows/mac/linux)。但我似乎没有找到一种方法来检查JAVA中的CPU使用率或不活动情况。谁能帮帮我?亲切的问候,兰诺伊

  7. 主题的 Javamail IMAP 搜索失败 - 2

    我在Gmail上使用javamail按主题搜索imap。我使用subjectTerm类创建一个searchTerm对象并传递给搜索函数。对于纯字母数字的主题字符串,搜索效果很好。只要我在搜索字符串中输入单引号或破折号,搜索就会失败。IMAPSSLStoreimapSslStore=connectToImap("imap.googlemail.com",993,email,oauthToken,oauthTokenSecret,getAnonymousConsumer(),true);Folderinbox=imapSslStore.getFolder("[Gmail]/AllMail"

  8. JavaMail API、Gmail-Auth 和 setFrom - 2

    对于这个应用程序,我遵循这个例子:http://pipoltek.blogspot.com/2008/02/sending-mail-using-gmail-smtp-server.html我可以发送电子邮件,它看起来不错.....但我想使用此修改发件人电子邮件:MimeMessagemsg=newMimeMessage(mailSession);msg.setFrom(newInternetAddress("baba-jaga@gmail.com"));baba-jaga@gmail.com是虚拟电子邮件,不是我的:)当我使用setFrom时,我会收到来自这封电子邮件的电子邮件,我用

  9. JavaMail - javax.mail.MessagingException - 2

    我正在尝试编写一个简单的邮件发件人类,该类将接收一堆参数并使用这些参数将使用我们的Exchange2010服务器发送电子邮件。虽然身份验证等似乎工作正常,但当代码实际尝试发送电子邮件时(我认为),我收到以下异常。我已确保身份验证正常工作,并且我从session中获得了传输,但它仍然失败。任何人都可以对我做错或遗漏的事情有所了解吗?谢谢。异常:javax.mail.MessagingException:[EOF]atcom.sun.mail.smtp.SMTPTransport.issueCommand(SMTPTransport.java:1481)atcom.sun.mail.smt

  10. JavaMail 检查邮件内容 gmail IMAP - 2

    我正在尝试阅读我的消息,我可以让它打印标题,但是发件人和内容显示得很有趣。这是我用来显示消息的代码:intj=message.length-1;for(inti=j;i>=0;i--){System.out.println("Message"+(i+1));System.out.println("From:"+message[i].getFrom());System.out.println("Subject:"+message[i].getSubject());try{System.out.println("Body:"+message[i].getContent());}catch(

随机推荐