EDIT:
see https://community.oracle.com/thread/1590625 https://community.oracle.com/thread/1590625
TL;DR 使用ByteArrayDataSource
必须深入研究Oracle的源代码......https://java.net/projects/javamail/sources/mercurial/content/mail/src/main/java/javax/mail/internet/MimeBodyPart.java https://java.net/projects/javamail/sources/mercurial/content/mail/src/main/java/javax/mail/internet/MimeBodyPart.java
当前的 java 邮件实现在输入流上执行 2 次:
- 首先确定是否应将标头“Content-Transfer-Encoding”设置为 7 位或 8 位(请参阅内容传输编码 7 位或 8 位 https://stackoverflow.com/questions/25710599/content-transfer-encoding-7bit-or-8-bit)
- 然后当它真正写入消息时第二次
...这很糟糕,因为whole流(在慢速连接上可能有数百 MB)将被读取两次......并且对于一旦读取就被“消耗”的流正是导致这个问题。
我尝试的第一个“解决方法”是自己指定标头:
attachmentPart.setDataHandler(new DataHandler(source));
attachmentPart.setHeader("Content-Transfer-Encoding", "8bit");
attachmentPart.setHeader("Content-Type", ds.getContentType() + "; " + ds.getName());
...按照这个顺序,而不是相反...因为出于某种原因setDataHandler
内部调用另一个方法invalidateContentHeaders
这清除了"Content-Transfer-Encoding"
再次标题(wtf?!)
Sounded great, the mail was sent, hooray!!! :D ... :( see next
附件已发送...但已损坏
我的邮件服务器中收到的文件已损坏。呵呵。Why?!。经过长时间的搜索并再次深入研究这个蹩脚的java邮件代码,我找到了它,他们通过管道传输了InputStream
into a LineOutputStream
这会改变你的行结尾binary数据。嗯。 java的邮件实现真是一团糟。 :/