Sending mail in OSGi shouldn't be hard. And, it wasn't, at least not at first. My code was working perfectly until it came time to work on some enhancements which required attachments. Suddenly my nice, simple mail program was falling over.
UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed
The problem is a typical OSGi classloading mess. In this case, javax.activation was unable to read a configuration file, META-INF/mailcap, that is normally a part of javax.mail. This file isn't needed for simple mail messages, but when you start adding attachments, you need it around. META-INF directories aren't something that can really be shared in OSGi, so there didn't seem like much hope of making things work correctly, at least short of creating (and maintaining) custom bundles.
I wasn't able to find any adequate solutions after a bit of searching. I tried using the springsource mail/activation bundles (making sure that I imported classes from those bundles rather than the system bundle) assuming they might have solved the problem, but javax.activation still had no visibility into javax.mail.
Digging through the code, I found that I could recreate the effects of META-INF/mailcap by directly calling CommandMap.setDefaultCommandMap(). That worked, but then the question became where to put that code. Do I create a service in my bundle to set these "global" values? What if some other clever bundle did the same thing? Maybe I should create a new bundle that did this setup, just to make sure I can turn it on and off easily. No matter what, this seemed ugly.
The other option was to embed javax.mail and javax.activation into my bundle. (Embed-Dependency using bnd) This physically puts the mail/activation jars inside the bundle and uses those classes before any system ones, making them private to the bundle in much the same way a JAR in WEB-INF/lib or some other Java EE archive would be. This would be a bad thing if I needed to share objects from those bundles to the outside world or if those bundles provided OSGi services, but that's clearly not the case here.
In the end, I've gone with the embedded JAR approach. It appears to solve my problems, and I'm able to fully use the libraries, at least as far as I can tell. Making the JARs private does bloat the bundles slightly, but I'm fully isolated from other JARs and from global side effects.
There's nothing magic about this solution, but since I wasn't able to find an adequate solution documented elsewhere, I thought it would be worthwhile to share what works. If anyone has a better solution, please post in the comments.