Java - SMTP Transporter要求SocketOutputStream无限期打开

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java - SMTP Transporter要求SocketOutputStream无限期打开相关的知识,希望对你有一定的参考价值。

在重构工作期间,我发现如果我使用“try-with-resources”关闭我的输出流 - 我总是从java的SMTPTransport获得MessagingException。它总是抱怨插座已关闭。

我发现有问题的代码是这样的:

try (LineOutputStream los = new LineOutputStream(os);) {
    los.writeln(signatureHeaderLine);
    Enumeration hdrLines = getNonMatchingHeaderLines(ignoreList);
    while (hdrLines.hasMoreElements()) {
        String notIgnoredLine = (String) hdrLines.nextElement();
        los.writeln(notIgnoredLine);
    }

    los.writeln();
    // Send signed mail to waiting DATA command
    os.write(osBody.toByteArray());
    os.flush();
} catch (MessagingException me) {
    // Deal with it
} catch (Exception e) {
    // Deal with it
}

上面的代码是MimeMessage.writeTo(OutputStream, String[])覆盖的一部分。当最终从SMTPTransport调用`issueSendCommand'和'sendCommand'时出现问题。

这是否意味着我的插座应该始终保持打开状态?我从非技术角度知道,关闭套接字感觉不对,因为我将通过它写消息。但我试图了解这是否会在将来因任何机会导致内存泄漏。

问候,

答案

我相信问题的出现是因为你在os语句之外使用OutputStream try-with-resource

try-with-resource语句确保在执行AutoClosable块后将关闭所有已初始化的try资源。在com.sun.mail.util.LineOutputStream关闭的那一刻,OutputStream os(传递给它的构造函数)也将被关闭。在os声明作用于已经关闭的try-with-resource后,任何访问OutputStream

编辑有一个例外,当OutputStream有一个没有效果的close()方法。例如ByteArrayOutputStream就是这种情况。

关闭ByteArrayOutputStream无效。在关闭流之后可以调用此类中的方法,而不会生成IOException。

一个片段来演示

private static void demoMethod(OutputStream os) throws IOException {
    try (LineOutputStream los = new LineOutputStream(os)) {
        los.writeln("signatureHeaderLine");
        los.writeln();
        os.write("foo".getBytes());
        System.out.println("within try-block");
    } catch (Exception e) {
        System.out.println(e);
    }
    os.write("bar".getBytes());
    System.out.println("after try-block");
}

demoMethod调用方法ByteArrayOutputStream

ByteArrayOutputStream os = new ByteArrayOutputStream();
demoMethod(os);

给出输出

within try-block
after try-block

因此,即使在调用ByteArrayOutputStream之后也可以使用close()(由try-with-resource代码调用的LineOutputStream.close()隐式调用它)。

FileOutputStream做同样的事情

FileOutputStream os = new FileOutputStream("/tmp/dummy.out");
demoMethod(os);

抛出异常,因为FileOutputStreamtry-with-resource声明结束时已经接近了。

within try-block
Exception in thread "main" java.io.IOException: Stream Closed
    at java.base/java.io.FileOutputStream.writeBytes(Native Method)
    at java.base/java.io.FileOutputStream.write(FileOutputStream.java:342)
    at Main.demoMethod(Main.java:24)
    at Main.main(Main.java:12)

以上是关于Java - SMTP Transporter要求SocketOutputStream无限期打开的主要内容,如果未能解决你的问题,请参考以下文章

sql 通过accounts_stated完成shipping.checked_at并通过shipment.transporter完成account_stated.transporter

无法通过SMTP服务器以Java发送邮件

App Store Connect 操作错误 Transporter 问题

Apple Transporter 错误代码 ITMS-4140 和 ITMS-6002

如何使用 Transporter 将 ipa 文件加载到应用商店? “构建”为空

java mail 发邮件连接不上smtp服务器怎么办