For a customer of mine I had another fine problem to resolve. He must send an email with a csv file as an attachment to his transport partner. The content for the csv file come from the database. Creating a string that has the contents for the file is easy, it would also be fairly easy to create a file, store it on the file system and add the file as an attachment. There is however one problem; I do not need the file after it has been attached to the email and send.

I started lookin at the api’s of springframework related to email. It is not that hard to find some code that looks like the following to create the email to be sent:

1. MimeMessage message = getJavaMailSender().createMimeMessage();
2. MimeMessageHelper helper = new MimeMessageHelper(message,true);
3. helper.setFrom(“from@gridshore.nl”);
4. helper.setTo(“to@gridshore.nl”);
5. helper.setText(“Text of the email”);
6. helper.setSubject(“attachment mail sample”);

Now for the fun part, how can we attach a generated csv file to the email without storing it on th efile system first.

7. InputStream attach = new ByteArrayInputStream(mailMessage.getBytes());
8. StreamAttachmentDataSource datasource = new StreamAttachmentDataSource(attach,”attachment”, “txt/plain”);
9. helper.addAttachment(attachmentName,datasource);
10.getJavaMailSender().send(message);

The fun part is in line 8, you must create a custom implementation for the org.springframework.core.io.AbstractResource. This resource must convert an inputstream to an attachment. The code for this class looks like this:

public class StreamAttachmentDataSource extends AbstractResource {
  private final static Log logger = LogFactory.getLog(StreamAttachmentDataSource.class);
  private ByteArrayOutputStream outputStream;
  private String name;
  private String contentType;

  public StreamAttachmentDataSource(InputStream inputStream, String name,
  String contentType) {
  this.outputStream = new ByteArrayOutputStream();
  this.name = name;
  this.contentType = contentType;

  int read;
  byte[] buffer = new byte[256];
  try {
  while((read = inputStream.read(buffer)) != -1) {
  getOutputStream().write(buffer, 0, read);
  }
  } catch (IOException e) {
  logger.error(“Cannot create inputstream for mail attachment”);
  throw new AddAttachmentMailException(“error.technical.mail.attachment”);
  }
  }

  public String getDescription() {
  return “Stream resource used for attachments”;
  }

  public InputStream getInputStream() throws IOException {
  return new ByteArrayInputStream(this.outputStream.toByteArray());
  }

  public String getContentType() {
  return contentType;
  }

  public String getName() {
  return name;
  }

  public ByteArrayOutputStream getOutputStream() {
  return outputStream;
  }

}

The hard part is not in the code, it is in finding the right code :-). What makes this a spring sample? I did use a number of utility classes from spring:
MimeMessageHelper – helps you with creating the mail message, a lot of try catch blocks less than with the standard way.
AbstractResource – This is a convenience class for creating your custom resources
JavaMailSender – Used to send messages that cannot be send as a SimpleMailMessage, implementation of th MailSender interface.

Using springframework to send an email with streaming attachment