By kaka2008


2011-04-15 13:27:15 8 Comments

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: invalid argument. JavaMail requires an InputStreamSource that creates a fresh stream for every call.

5 comments

@Ralph 2011-04-15 14:14:45

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("[email protected]");

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

@kaka2008 2011-04-16 04:13:08

yeah,i know this. what i wanna know is how to send attachment with a InputStream Object rather than a file. because i generate a file in the memory , i don't want to save it on the disk.

@ptr07 2011-07-02 07:30:24

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)));

@Kefirchiks 2017-06-09 14:33:40

Thank you. Works perfectly.

@Scala Enthusiast 2018-06-12 15:40:44

This can also be done without a library using the following: helper.addAttachment(ATTACHMENT_FILE_NAME, new ByteArrayResource(attachmentContent.getBytes(StandardCharset‌​s.UTF_8)), MediaType.TEXT_HTML.toString());

@Khuynh Thành Chi Luyến 2020-08-05 11:47:26

since attachment is converted to byte[], is there a way that we can attach a file with size is bigger than 2GB?

@Sergey Chepurnov 2019-02-06 10:54:56

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("[email protected]");
    helper.setTo("[email protected]");
    helper.setReplyTo("[email protected]");
    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("[email protected]");
        helper.setTo("[email protected]");
        helper.setReplyTo("[email protected]");
        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;
   }
   //...
}

@Sujith 2015-05-11 03:52:10

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

@Michal Moravcik 2012-02-15 23:24:43

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);

Related Questions

Sponsored Content

74 Answered Questions

34 Answered Questions

[SOLVED] Convert InputStream to byte array in Java

95 Answered Questions

[SOLVED] How to validate an email address in JavaScript

43 Answered Questions

[SOLVED] How do I efficiently iterate over each entry in a Java Map?

58 Answered Questions

[SOLVED] How to create a memory leak in Java?

66 Answered Questions

[SOLVED] How do I generate random integers within a specific range in Java?

  • 2008-12-12 18:20:57
  • user42155
  • 4110640 View
  • 3549 Score
  • 66 Answer
  • Tags:   java random integer

29 Answered Questions

23 Answered Questions

[SOLVED] Sending email in .NET through Gmail

59 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

Sponsored Content