开发者

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();
        }
      }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜