JavaMail:是否可以在连接期间临时启用Store调试?

时间:2018-05-25 10:33:48

标签: javamail

我的团队有一个运行时间很长的IMAP邮箱监听器,它使用JavaMail v1.6.1(编写时最新的http://search.maven.org)以及IMAP IDLE命令来自动处理收到的邮件。服务器是Microsoft Exchange 2010,但我不知道确切的补丁级别。

不幸的是,有时我们会看到非常奇怪的行为。经过3.5小时的IDLE(等待传入邮件)后,我们的连接突然关闭。 (我们假设服务器正在关闭我们的连接。)通常,重新打开逻辑工作。但是,在某些时候,邮件服务器变得“脾气暴躁”并拒绝重新连接:javax.mail.AuthenticationFailedException: LOGIN failed.

我已经阅读了足够的JavaMail博客文章和Q& As(由不知疲倦的倡导者和帮助者Bill Shannon)来了解问题可能在我们的代码中,而不是JavaMail或IMAP服务器中的错误。

是否可以在连接期间临时启用Store调试?

我们正在尝试各种Session属性...理想情况下,我希望在Store实例的连接期间暂时启用调试。但是,查看IMAPSSLStore(扩展extends IMAPStore)的实现,似乎调试标志来自父Session实例,并且以后无法在Store实例上更改。此外,由于我们只有偶尔在连接3.5小时后才能看到问题,因此如果在我们的应用程序中启用了JavaMail调试日志记录将会非常大。

供参考,这是我们的初始连接代码:

    final Properties p = new Properties();
    // Ref: https://community.oracle.com/message/10503406?#10501406
    // Ref: https://stackoverflow.com/questions/11719205/how-to-use-javamail-for-accessing-additional-mailboxes-imap-exchange-2010
    p.setProperty("mail.imaps.ssl.enable", "true");
    p.setProperty("mail.imaps.auth.plain.disable", "true");
    p.setProperty("mail.imaps.auth.ntlm.disable", "true");
    p.setProperty("mail.imaps.auth.gssapi.disable", "true");
    p.setProperty("mail.imaps.starttls.enable", "false");
    p.setProperty("mail.imaps.host", config.host);
    p.setProperty("mail.imaps.port", String.valueOf(config.port));
    p.setProperty("mail.imaps.socketFactory.fallback", "false");
    // Ref: https://stackoverflow.com/questions/35532797/how-to-speed-up-time-when-using-java-mail-to-save-attachments
    p.setProperty("mail.imaps.partialfetch", "false");
    p.setProperty("mail.imaps.fetchsize", "1048576");

    // Ref: http://www.obsidianscheduler.com/blog/ignoring-self-signed-certificates-in-java/
    final SSLContext c =
        // Ref: https://stackoverflow.com/a/13138554/257299
        SSLContext.getInstance("TLS");
        // SSLContext.getInstance("SSL");
        // SSLContext.getDefault();
    c.init(
        (KeyManager[]) null,
        new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                throws CertificateException {
                    @DebugBreakpoint int dummy = 1;
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                throws CertificateException {
                    @DebugBreakpoint int dummy = 1;
                }

                @Override
                public X509Certificate[]
                getAcceptedIssuers() {
                    return null;
                }
            }
        },
        (SecureRandom) null);

    final SSLSocketFactory socketFactory = c.getSocketFactory();
    p.put("mail.imaps.ssl.socketFactory", socketFactory);

    final Session session = Session.getInstance(p);
    // Ref: https://stackoverflow.com/questions/30613622/java-mail-store-type-imap-vs-imaps
    final Store store = session.getStore("imaps");  // Type: IMAPSSLStore
    store.connect(config.username, config.password);

1 个答案:

答案 0 :(得分:1)

如果为每个连接使用不同的会话,则可以基于每个会话(以及每个连接)启用调试。如果您提供自己的调试OutputStream,则可以决定是丢弃调试输出还是保留它。

JavaMail调试也通过java.util.logging发送。您应该能够动态启用和禁用记录器,但请注意,这适用于整个JVM,而不仅仅适用于Store。您可以使用线程局部变量和您自己的日志处理程序来进一步过滤日志输出。

另外,请注意,您不需要自己的套接字工厂。您可以设置https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/configuring-aspnet-web-api#webhost属性。