I recently created a small bundle, JMAPI, to provide support for programmatically opening an email message on Windows platforms using MAPI. Although the bundle’s functionality is restricted to Windows, the bundle is cross-platform. The API is through a single class, jmapi.JMAPI, which supports three methods, one of which queries whether MAPI support is available.
JMAPI was carved from the ruins of the old Java Desktop Interface Components (JDIC) project. With most of JDIC’s functionality has was absorbed into Java 6’s java.awt.Desktop class, JDIC seems to have died. Not to mention that its binary distributions were wiped out with Oracle’s transfer of java.net to Kenai.
The one useful component from JDIC that wasn’t absorbed was its attempt to provide cross-platform support for opening mail messages in the user’s mail client. Java 6 only supports the mailto: URL scheme. Although mailto: is useful, it is length-limited and, more importantly, doesn’t provide for specifying message attachments; some clients provide for an “attachment” field, but its support is uneven.
Unfortunately JDIC’s binary distribution is not OSGi-friendly. As my immediate needs were for a way to programmatically open a message using MAPI, I simply ripped out the support from JDIC, and did the minimum to make it work as an OSGi bundle. I didn’t have the time to figure out how to rebuild the JNI support libraries (it has references to MFC and ATL), so I simply copied in the Windows DLL from JDIC 0.9.5; unfortunately this is 32-bit only. It may be possible to build using VisualStudio Express 2010 by someone with more Microsoft mojo than me.
Be aware that non-Outlook clients, such as Thunderbird, may need to perform a few extra steps to ensure that they are properly registered as the default email client.
Source is available up on github and is licensed under the same terms as JDIC with the LGPL.
[…] doing some development on a large RCP application. One recent task required using a Windows DLL to open an email message through MAPI. I encountered a few issues that I’m sure will bite other […]
By: Bundle-NativeCode: Using platform-specific DLLs from OSGi « holistic tendencies on March 29, 2011
at 4:04 pm
Hi Brian,
I have the exact similar requirement in which i have to attach the files in the default mail client. I downloded your code files from the link http://github.com/briandealwis/jmapi
And imported the project in eclipse(RSA). I created a test file with the code
But when i try to run the file, i get the following error
Requesting your help in resolving this.
Thanks
Aims
By: Aims on November 20, 2012
at 3:27 pm
My guess: you’re using a 64-bit JVM? The JMAPI library is 32-bit only, unfortunately.
By: Brian de Alwis on November 20, 2012
at 3:31 pm
Sorry but can you help me understand where can i check if its 32bit or 64 bit? I am running on Windows XP 2002 SP3.
Thanks
Aims
By: Aims on November 21, 2012
at 12:04 am
When i run the java -version i got the following output
java version “1.6.0_29”
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) Client VM (build 20.4-b02, mixed mode, sharing)
By: Aims on November 21, 2012
at 12:13 am
See StackOverflow
By: Brian de Alwis on November 21, 2012
at 5:19 am
I checked and it is 32 bit only. Can u suggest anything to fix this?
Also can you explain if this will work with 32bit JVM installed on 64bit OS?
Thanks
Aims
By: Aims on November 21, 2012
at 11:10 am
If your 32-bit JVM works on your 64-bit OS, then this should work too. The only thing that comes to mind is that the DLL is not being resolved: ensure that it is on your PATH or java.lib.path (that is, providing you’re not using the bundle via OSGi), and verify that all the dependencies are being found with something like DependencyWalker.
By: Brian de Alwis on November 21, 2012
at 2:02 pm
Yes it is working now. Thanks for all the help.
Is there a version available for the 64bit as well now?
Thanks
Aims
By: Aims on November 23, 2012
at 6:05 am
When I was using this stuff, MAPI was 32-bit only. It seems there’s now 64-bit support too. I don’t have cycles to look into this further, but feel free to investigate and report back.
By: Brian de Alwis on November 24, 2012
at 10:29 am
when i will run my code on server it will show following exception:::>
org.jdesktop.jdic.desktop.internal.LaunchFailedException: Logon failed: Unexpected exception
24 Nov 2012 20:41:22,904 http-8080-3 DEBUG annotation.ResponseStatusExceptionResolver – Resolving exception from handler [com.axa.ebi.controller.TopazController@1b00766]: org.jdesktop.jdic.desktop.internal.LaunchFailedException: Logon failed: Unexpected exception
24 Nov 2012 20:41:22,904 http-8080-3 DEBUG support.DefaultHandlerExceptionResolver – Resolving exception from handler [com.axa.ebi.controller.TopazController@1b00766]: org.jdesktop.jdic.desktop.internal.LaunchFailedException: Logon failed: Unexpected exception
24 Nov 2012 20:41:22,904 http-8080-3 DEBUG
servlet.DispatcherServlet – Could not complete request
By: janak on November 24, 2012
at 10:35 am
Why are you using MAPI on a server? Couldn’t you use java-mail instead?
By: Brian de Alwis on November 24, 2012
at 10:54 am
my requirement is to attached selected document document on email client. when i will run my code on spring source tool server than it will working file. but when i will deploy war file on tomcat server and run at that time it will give me exception:
“org.jdesktop.jdic.desktop.internal.LaunchFailedException: Logon failed: Unexpected exception”.
my code given below.
System.loadLibrary(“jdic”);
if (JMAPI.isMapiSupported()) {
Message msg = new Message();
//msg.setSubject(“test!”);
// msg.setBody(“Hello world”);
/*List toAddresses = new LinkedList();
toAddresses.add(“example@example.com”);
msg.setToAddrs(toAddresses);
*/
List attachPaths = new LinkedList();
//Must be absolute paths to file
for(int i=0;i<dbpdfFileName.size();i++)
{
String pdfFilePath =(String) dbpdfFileName.get(i);
//System.out.println("printpdf_pdfFilePath:::"+pdfFilePath);
if (logger.isDebugEnabled())
{
logger.debug(moduleName + className + "viewstaicpdf" + "pdfFilePath::" + pdfFilePath);
}
File file = new File(pdfFilePath);
boolean exists = file.isFile();
if (logger.isDebugEnabled())
{
logger.debug(moduleName + className + "viewstaicpdf" + "File is exist ?::" + exists);
}
if (exists)
{
attachPaths.add(pdfFilePath);
}
}
msg.setAttachments(attachPaths);
JMAPI.open(msg);
}
By: janak on November 25, 2012
at 4:44 am
Hi all, Actually I tried using above code to open email
client with automatically attached document. But for me it is
showing nothing and when i am getting that JMAPI.isSupported value
as false for entering into loop. Because I tried to print the
boolean value of that and it shown false. Can any one help me on
this to how can I use this code in a correct way to open a email
client with an attached pdf or any file. Pls do needful..
By: Ashok on November 27, 2012
at 5:05 am
Hi Brian, I am running 32 bit Window Xp machine. I am able
to laod the dll. But Still I am getting false for
JMAPI.isMapiSupported(). Is this possible if yes, How can i make it
to return true ? Thanks in Advance! -Manish
By: manish on December 6, 2012
at 9:43 am
Sounds like you’re either running on a 64-bit JVM or the DLL can’t be loaded. If you’re executing ominous a non-OSGi environment, you’ll need to ensure the included DLL is on your PATH.
By: Brian de Alwis on January 13, 2013
at 6:41 am
I am trying to use JMAPI in my application. I am getting
the following error: java.lang.UnsatisfiedLinkError:
org.jdesktop.jdic.desktop.internal.impl.WinAPIWrapper.RegOpenKey(I[BI)[I
at
org.jdesktop.jdic.desktop.internal.impl.WinAPIWrapper.RegOpenKey(Native
Method) at
org.jdesktop.jdic.desktop.internal.impl.WinAPIWrapper.WinRegQueryValueEx(WinAPIWrapper.java:170)
at jmapi.JMAPI.isMapiSupported(JMAPI.java:40) at
com.turborep.turbotracker.mail.SendQuoteMail.send(SendQuoteMail.java:120)
at com.turborep.turbotracker.mail.SendEmail.main(SendEmail.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597) at
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212)
at
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
at
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
at
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
at
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662) My machine details: OS:
Ubuntu 12.04 my code: if (JMAPI.isMapiSupported()) { Message msg =
new Message(); msg.setSubject(“test!”); msg.setBody(“Hello world”);
List toAddresses = new LinkedList();
toAddresses.add(“gopi.nath@sysvine.com”);
msg.setToAddrs(toAddresses); List attachPaths = new LinkedList();
//Must be absolute paths to file
attachPaths.add(attachFile.getPath());
msg.setAttachments(attachPaths); JMAPI.open(msg); } Can you please
help me on this.
By: vish on January 10, 2013
at 10:47 am
How can I send the email directly without opening the defualt mail client beforehand? is this not possible with MAPI32 ?
By: Markus.Haudum@gmail.com on July 10, 2013
at 7:59 am
I don’t believe MAPI allows that to prevent trojans and worms from (easily) sending messages without the user’s approval. Use the java-mail APIs instead.
By: Brian de Alwis on July 10, 2013
at 9:16 am
The lack of support for 64-bit isn’t the only problem. This could probably be fixed. The real problem is that JMAPI uses the “Simple MAPI” interface in Windows. This is discouraged. From Microsoft docs:
“The use of Simple MAPI functions is discouraged. They may be altered or unavailable in subsequent versions of Windows.”
Link: https://msdn.microsoft.com/en-us/library/windows/desktop/dd296728%28v=vs.85%29.aspx
It is not entirely clear to me what the alternative to “Simple MAPI” is, but it seems to be what is known as “Extended MAPI”.
By: Peter on January 24, 2016
at 5:50 pm
I had an issue about this and fixed it by adding an entry into the registry.
Registry field is…
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Messaging Subsystem
The value must be “MAPI” and the contents must be a STRING and have a value of “1” on a windows 10 x64 system.
By: David Irving on May 19, 2021
at 3:47 am