关于Java:如何使用InputStream和Spring发送带有附件的电子邮件?

How to send email with attachment using InputStream and Spring?

情况是这样的:

首先,我们在内存中生成一个文件,我们可以得到一个InputStream对象。
其次,InputStream对象必须作为电子邮件的附件发送。 语言是Java,我们使用Spring发送电子邮件。

我发现了很多信息,但是找不到使用InputStream发送电子邮件附件的方法。 我尝试这样做:

1
2
3
InputStreamSource iss= new InputStreamResource(new FileInputStream("c:\\\\a.txt"));
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true,"UTF-8");
message.addAttachment("attachment", iss);

但我有一个例外:

Passed-in Resource contains an open stream: invalid argument. JavaMail
requires an InputStreamSource that creates a fresh stream for every
call.


对于内存中生成的文件,可以使用ByteArrayResource。只需使用Apache Commons IO库中的IOUtils转换您的InputStream对象。

这很简单:

1
2
helper.addAttachment("attachement",
new ByteArrayResource(IOUtils.toByteArray(inputStream)));


看看spring参考章节24.3使用JavaMail MimeMessageHelper

这个例子是从那里开始的,我想它确实想要您要做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);

如果要使用流,则可以使用

1
ByteArrayResource resource = new ByteArrayResource(IOUtils.toByteArray(inputStream)));

而不是FileSystemResource


您可以根据需要对InputStreamSource进行简单实现,并在其中传递新鲜的InputStream:

1
2
3
4
5
6
7
8
9
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);

工作示例是:

1)附件是InputStreamSource接口

1
2
3
4
5
6
7
8
9
10
11
12
13
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)附件是DataSource接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
    }

说明:

Passed-in Resource contains an open stream: invalid argument.
JavaMail requires an InputStreamSource that creates a fresh stream for
every call.

如果开发人员使用InputStreamSource的实现在isOpen()方法中返回true,则可能会出现此消息。

方法MimeMessageHelper#addAttacment()中有一个特殊检查:

1
2
3
4
5
6
7
8
9
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()总是返回true,这使得无法将此实现用作附件:

1
2
3
4
5
6
7
8
public class InputStreamResource extends AbstractResource {
   //...
   @Override
   public boolean isOpen() {
      return true;
   }
   //...
}

// inlineFileObjectCreated-您可以创建一个StringBuilder对象作为示例

1
2
3
4
5
6
7
8
9
10
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());

//////////////////////////////////////////////////

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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();
        }
      }