首页 > 解决方案 > MimeMessage.writeTo(OutputStream) 挂起

问题描述

我正在尝试通读邮箱中的邮件,但是在将邮件内容解析到 MimeMessage 期间,某些特定邮件使进程挂起,它不显示任何错误消息,日志显示程序在 MimeMessage.writeTo 步骤停止(OutputStream),下面是实际代码

for (int n = message.length; i < n; i++)
            {Log25.write("IMAPaccess", "getMessages", "start convert");
                MimeMessage msg = (MimeMessage)message[i];
                Log25.write("IMAPaccess", "getMessages", "A");
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                Log25.write("IMAPaccess", "getMessages", "B");
                msg.writeTo(bos);
                Log25.write("IMAPaccess", "getMessages", "C");
                bos.close();
                Log25.write("IMAPaccess", "getMessages", "start create bis");
                SharedByteArrayInputStream bis = new SharedByteArrayInputStream(bos.toByteArray());
                MimeMessage cmsg = new MimeMessage(session, bis);
                bis.close();

....

下面是日志信息,它没有显示任何异常,而是挂在“msg.writeTo(bos);”步骤的“B”处 在日志中

Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     36:     [Ljavax.mail.internet.InternetAddress;@d522e24d null
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     36: From address length         1
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     36: From address        INFORMATION <info@funds.com>
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     complete for loop j
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     start convert
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     A
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     B
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     C
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     start create bis
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     start cmsg to mimeMessage
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     content type: text/html;^M
        charset="utf-8"
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     37:     [Ljavax.mail.internet.InternetAddress;@9b58d2b8 null
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     37: From address length         1
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     37: From address        =?utf-8?B?6ZyN6bmD5Y6a?= <1757158944@qq.com>
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     complete for loop j
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     start convert
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     A
Mon Sep 10 09:44:41 UTC 2018    IMAPaccess      getMessages     B

标签: javaemailjakarta-mail

解决方案


最终我放弃了转换消息类型,如果转换挂了我直接让for循环跳过继续,这样就省略了一些消息。我认为这无关紧要,因为我发现只有垃圾邮件才能使程序挂起。下面是代码

for (int n = message.length; i < n; i++)
            {   
                Log25.write("IMAPaccess", "getMessages", "start convert");
                MimeMessage msg = (MimeMessage)message[i];

                ByteArrayOutputStream bos = new ByteArrayOutputStream();


                // MJN1 has some SPAM email cannot be converted, so use thread to do the conversion 
                final Runnable stuffToDo = new Thread() {
                      @Override 
                      public void run() { 
                          try {
                            Log25.write("IMAPaccess", "run", "write to MimeMessage");
                            msg.writeTo(bos);
                            Log25.write("IMAPaccess", "run", "wrote to MimeMessage");
                        } catch (IOException | MessagingException e) {
                            Log25.write("IMAPaccess", "run", (new StringBuilder()).append("error = ").append(e.getMessage()).toString());

                        }
                      }
                    };

                final ExecutorService executor = Executors.newSingleThreadExecutor();
                final Future future = executor.submit(stuffToDo);
                executor.shutdown(); // This does not cancel the already-scheduled task.

                // start the conversion and if the process hangs, the loop should skip and continue
                try { 
                  future.get(1, TimeUnit.SECONDS); 
                }
                catch (InterruptedException ie) { 
                    Log25.write("IMAPaccess", "getMessages", (new StringBuilder()).append("error = ").append(ie.getMessage()).toString());
                    continue;
                }
                catch (ExecutionException ee) { 
                    Log25.write("IMAPaccess", "getMessages", (new StringBuilder()).append("error = ").append(ee.getMessage()).toString());
                    continue;
                }
                catch (TimeoutException te) { 
                    Log25.write("IMAPaccess", "getMessages", (new StringBuilder()).append("error = ").append(te.getMessage()).toString());
                    continue;
                }
                catch(Exception e) {
                    Log25.write("IMAPaccess", "getMessages", (new StringBuilder()).append("error = ").append(e.getMessage()).toString());
                    continue;
                }
                if (!executor.isTerminated())
                    executor.shutdownNow();

                bos.close();

我使用线程和执行程序使挂起循环继续,这不是一件容易的事。


推荐阅读