1

I am using a virtual filesystem and I'd like to attach a file from it to an email. However, the MimeBodyPart object only takes Files, which don't work on a default filesystem like jimfs. See my code below, where I get an UnsupportedOperation exception when I try to convert to file.

public Email attach(Path file){
    MimeBodyPart attachment = new MimeBodyPart()
    attachment.attachFile(file.toFile())
    attachments.add(attachment)
    return this
}
Steve
  • 4,457
  • 12
  • 48
  • 89
  • What version of the API are you using? Is the unsupportedOperation occurred on attaching the file to MimeBodyPart or File.toFile() that does not support virtual filesystem? – Minh Kieu Jun 06 '17 at 15:01
  • the file.toFile() call is throwing the unsupported exception, because jimfsPath does not implement that method. I'm using java 8. As far as I can tell MimeBodyPart only knows how to interact with Files, not Path objects. – Steve Jun 06 '17 at 16:54
  • Ok So if I understand you correctly, you need to use the jimfs API, write the file into the filesystem and then attach to the MimeBodyPart class. The advanced method is to "extends" File and override the methods which would allow dynamic stream of the content from jimfs. However, I would stick to the simple approach first. – Minh Kieu Jun 06 '17 at 17:01

2 Answers2

3

Since jimfs files aren't really files, you can't use the File APIs.

A simple workaround is to use ByteArrayDataSource, which will copy the data.

A better approach would be to write your own PathDataSource that's similar to FileDataSource but uses Files.newInputStream instead of FileInputStream. Then attach the file using:

MimeBodyPart mbp = new MimeBodyPart();
mbp.setDataHandler(new DataHandler(new PathDataSource(path)));
mbp.setFileName(path.getFileName().toString());
mbp.setDisposition(Part.ATTACHMENT);
Bill Shannon
  • 29,579
  • 6
  • 38
  • 40
1

Whatever this MimeBodyPart API is really ought to have an option to use a Path so that you could just use the Jimfs file directly, but since the java.nio.file APIs require Java 7 and don't work on Android yet many libraries unfortunately don't support Path yet.

toFile() can never work for a Jimfs file, or for any file that isn't on the default file system, because the File class can only represent files on the default file system. So yeah, you'd need to copy the Jimfs file to the real file system to use this attachFile method.

If the MimeBodyPart API had an option for using a URL or URI for the attachment, you would probably be able to use that plus file.toUri()[.toURL()]. Or if it could use, say, an InputStream you could obviously get one of those from the file and use it instead.

ColinD
  • 108,630
  • 30
  • 201
  • 202
  • Looks like I might be in the market for a new mail api :/ – Steve Jun 06 '17 at 18:41
  • 1
    @Steve Use [javax.activation.URLDataSource](https://docs.oracle.com/javase/7/docs/api/javax/activation/URLDataSource.html). Then use the example code from @bill-shannon but use this `mbp.setDataHandler(new DataHandler(new URLDataSource(path.toUri().toURL())))` as the source. – jmehrens Jun 06 '17 at 21:19
  • If jimfs provides real URLs that are usable with URLConnection, that would work too. – Bill Shannon Jun 06 '17 at 23:00
  • I have a related question here, https://stackoverflow.com/questions/44378292/java-uri-pointing-to-virtual-filesystem. Turning my path into a URI seems to work for emails, but not for zipfiles :/ – Steve Jun 07 '17 at 16:00
  • @BillShannon: Jimfs does indeed provide `URL`s that are usable with `URLConnection`. Though I think your solution is a good one. – ColinD Jun 07 '17 at 19:26