How to send email with attachment using InputStream and Spring?
The situation is like this:
First, we generate a file in the memory, we can get a InputStream
object.
Second the InputStream object must be send as a attachment of a email. The language is Java, we use Spring to send email.
I have found a lot of information, but I cannot find how to send an email attachment using InputStream
. I try to do like this:
InputStreamSource iss= new InputStreamResource(new FileInputStream("c:\\a.txt"));
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
message.addAttachment("attachment", iss);
But I get an exception:
Passed-in Resource contains an open stream开发者_JAVA技巧: invalid argument. JavaMail requires an InputStreamSource that creates a fresh stream for every call.
For files generated in memory, you may use ByteArrayResource
. Just convert your InputStream
object using IOUtils
from the Apache Commons IO library.
It is quite simple:
helper.addAttachment("attachement",
new ByteArrayResource(IOUtils.toByteArray(inputStream)));
Have a look at the spring reference chapter 24.3 Using the JavaMail MimeMessageHelper
The example is from there, I think it do want you want to do:
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessage message = sender.createMimeMessage();
// use the true flag to indicate you need a multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo("test@host.com");
helper.setText("Check out this image!");
// let's attach the infamous windows Sample file (this time copied to c:/)
FileSystemResource resource = new FileSystemResource(new File("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg", resource );
sender.send(message);
if you want to use a Stream, then you can use
ByteArrayResource resource = new ByteArrayResource(IOUtils.toByteArray(inputStream)));
instead of FileSystemResource
You can make simple implementation of InputStreamSource and pass fresh InputStream in it, as requested:
InputStreamSource iss = new InputStreamSource() {
@Override
public InputStream getInputStream() throws IOException {
// provide fresh InputStream
return new FileInputStream("c:\\a.txt");
}
}
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
message.addAttachment("attachment", iss);
The working examples are:
1) Attachment is an InputStreamSource
interface
public void send() throws IOException, MessagingException {
final ByteArrayOutputStream stream = createInMemoryDocument("body");
final InputStreamSource attachment = new ByteArrayResource(stream.toByteArray());
final MimeMessage message = javaMailSender.createMimeMessage();
final MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setSubject("subject");
helper.setFrom("from@from.com");
helper.setTo("to@to.com");
helper.setReplyTo("replyTo@replyTo.com");
helper.setText("stub", false);
helper.addAttachment("document.txt", attachment);
javaMailSender.send(message);
}
2) Attachment is an DataSource
interface
public void send() throws IOException, MessagingException {
final ByteArrayOutputStream document = createInMemoryDocument("body");
final InputStream inputStream = new ByteArrayInputStream(document.toByteArray());
final DataSource attachment = new ByteArrayDataSource(inputStream, "application/octet-stream");
final MimeMessage message = javaMailSender.createMimeMessage();
final MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setSubject("subject");
helper.setFrom("from@from.com");
helper.setTo("to@to.com");
helper.setReplyTo("replyTo@replyTo.com");
helper.setText("stub", false);
helper.addAttachment("document.txt", attachment);
javaMailSender.send(message);
}
The explanation:
Passed-in Resource contains an open stream: invalid argument. JavaMail requires an InputStreamSource that creates a fresh stream for every call.
This message could appear if the developer use an implementation of InputStreamSource
that return true
in the isOpen()
method.
There is a special check in the method MimeMessageHelper#addAttacment()
:
public void addAttachment(String attachmentFilename, InputStreamSource inputStreamSource, String contentType) {
//...
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
throw new IllegalArgumentException(
"Passed-in Resource contains an open stream: invalid argument. " +
"JavaMail requires an InputStreamSource that creates a fresh stream for every call.");
}
//...
}
InputStreamResource#isOpen()
always return true
that makes impossible to use this implementation as an attachment:
public class InputStreamResource extends AbstractResource {
//...
@Override
public boolean isOpen() {
return true;
}
//...
}
//inlineFileObjectCreated -- you can create a StringBuilder Object for a example
ByteArrayDataSource source = new ByteArrayDataSource("file name", "contentType", inlineFileObjectCreated.getBytes() );
JavaMailSender mailSender = (JavaMailSender) ServicesHome.getService("javaMailSender");
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setTo(toArray);
mimeMessageHelper.setSubject("");
mimeMessageHelper.setText("");
mimeMessageHelper.addAttachment("filename", source);
mailSender.send(mimeMessageHelper.getMimeMessage());
/////////////////////////////////////////////
import javax.activation.DataSource;
public class ByteArrayDataSource implements DataSource {
byte[] bytes;
String contentType;
String name;
public ByteArrayDataSource( String name, String contentType, byte[] bytes ) {
this.name = name;
this.bytes = bytes;
this.contentType = contentType;
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() {
return new ByteArrayInputStream(bytes);
}
public String getName() {
return name;
}
public OutputStream getOutputStream() throws IOException {
throw new FileNotFoundException();
}
}
精彩评论