是否可以使用 javax.mail
发送电子邮件并使用“现有”InputStream
作为电子邮件附件内容?
目前我正在构建如下电子邮件消息:
final MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("Subject line");
final Multipart multipartContent = new MimeMultipart();
final MimeBodyPart textPart = new MimeBodyPart();
textPart.setText("Message body");
multipartContent.addBodyPart(textPart);
final MimeBodyPart attachmentPart = new MimeBodyPart();
final DataSource source = new InputStreamDataSource("text/plain", "test.txt", new ByteArrayInputStream("CONTENT INPUT STREAM".getBytes()));
attachmentPart.setDataHandler(new DataHandler(source));
attachmentPart.setFileName("text.txt");
multipartContent.addBodyPart(attachmentPart);
message.setContent(multipartContent);
InputStreamDataSource
实现如下:
public class InputStreamDataSource implements DataSource
{
private final String contentType;
private final String name;
private final InputStream inputStream;
public InputStreamDataSource(String contentType, String name, InputStream inputStream)
{
this.contentType = contentType;
this.name = name;
this.inputStream = inputStream;
}
public String getContentType()
{
return contentType;
}
public String getName()
{
return name;
}
public InputStream getInputStream() throws IOException
{
System.out.println("CALLED TWICE: InputStreamDataSource.getInputStream()");
return new BufferedInputStream(inputStream);
//return new ByteArrayInputStream("THIS 'NEW' INPUT STREAM WORKS BUT 'EXISTING' INPUT STREAM RESULTS IN ZERO-BYTE ATTACHMENT".getBytes());
}
public OutputStream getOutputStream() throws IOException
{
throw new UnsupportedOperationException("Not implemented");
}
}
DataSource
提供方法getInputStream()
来获取电子邮件附件内容的InputStream
。
如果我返回一个不依赖于“现有”InputStream
的"new"InputStream
,那么它可以正常工作。但是,如果我返回一个“现有的”InputStream,那么电子邮件将以一个零字节的附件发送。
是否可以使用 javax.mail
发送电子邮件,并使用“现有”InputStream
作为电子邮件附件内容?
最佳答案
编辑:
参见 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
当前的 java 邮件实现在输入流上运行了 2 次:
- 首先确定是否应该将 header “Content-Transfer-Encoding”设置为 7 位或 8 位(参见 Content Transfer Encoding 7bit or 8 bit)
- 然后在它实际写入消息时第二次
...这有点糟透了,因为整个流(在慢速连接上可能有数百 MB)将被读取两次...并且对于“消费”一次阅读。
我尝试的第一个“解决方法”是自己指定 header :
attachmentPart.setDataHandler(new DataHandler(source));
attachmentPart.setHeader("Content-Transfer-Encoding", "8bit");
attachmentPart.setHeader("Content-Type", ds.getContentType() + "; " + ds.getName());
...并按此顺序,而不是相反...因为某些原因 setDataHandler
在内部调用另一个方法 invalidateContentHeaders
清除 “Content-Transfer-Encoding”
再次 header (wtf?!)
听起来很棒,邮件已发送,万岁!!! :D ... :( 看下一个
附件已发送...但已损坏
我的邮件服务器中收到的文件已损坏。嗯。 为什么?!。经过长时间的搜索并再次深入研究这个蹩脚的 java 邮件代码,我找到了,他们将 InputStream
通过管道传输到 LineOutputStream
中,这会更改 二进制文件的行尾 数据。嗯。 java邮件实现真是一团糟。 :/
关于java - 使用现有 InputStream 作为附件内容使用 javax.mail 发送电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34009587/