0

I am trying to build a Java Drag and Drop that works with Outlook emails. I've been using Jacob because of an inability to transfer data from Outlook to Java using standard AWT Event stuff. That said, all of the solutions I've pulled from here or other sites have been causing a fatal crash in Java. Here's the code:

import java.awt.dnd.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.io.*;
import java.util.List;
import sun.awt.datatransfer.*;
import com.jacob.com.*;
import com.jacob.activeX.*;
public class D2 extends JFrame
{

private static final String DIR = "FILES";

private static void saveSelectedOutlookMails(String directory) {

    Dispatch xl = new Dispatch("Outlook.Application");

    //Dispatch selection = Dispatch.get(xl, "Selection").toDispatch();

    System.out.println(xl);
    System.out.println(xl==null);
    //PROGRAM CRASHES AFTER THIS LINE
    Dispatch explorer = Dispatch.get(xl,"ActiveExplorer").toDispatch();
    System.out.println("explorer");
    Object selection = Dispatch.get(explorer, "Selection").toDispatch();
    Variant count = Dispatch.get(selection, "Count");

    for (int mailIndex = 1; mailIndex <= count.toInt(); mailIndex++ ) {
        Object mailItem = Dispatch.call(selection, "Item", new Variant(mailIndex)).toDispatch();

        Variant senderName = Dispatch.get(mailItem, "SenderName");
        Variant subject = Dispatch.get(mailItem, "Subject");
        Variant body = Dispatch.get(mailItem, "Body");

        String emailFileName = subject.toString() +".txt"; 

        String fullPath = directory + "/" + emailFileName;
        try {
            File email = new File(fullPath);
            PrintWriter writer = new PrintWriter( new FileWriter(email) );
            writer.println("From: "+ senderName );
            writer.println("Subject: "+ subject);
            writer.println("");
            writer.print( body );
            writer.close();
        }
        catch (IOException e) {

            System.out.println(e.getMessage());
            //logger.error("IOException writing e-mail with subject: '"+ subject +"'", e);
            continue;
        }

        Object attachments = Dispatch.get(mailItem, "Attachments").toDispatch();
        Variant attachmentCount = Dispatch.get(attachments, "Count");

        if ( attachmentCount.toInt() > 0 ) {

            for( int attachmentIndex = 1; attachmentIndex<=attachmentCount.toInt(); attachmentIndex++ ) {

                Object attachment = Dispatch.call(attachments, "Item", new Variant(attachmentIndex)).toDispatch();
                Variant fileNameVariant = Dispatch.get(attachment, "FileName");
                String fileName = fileNameVariant.toString();

                Variant saveResult = Dispatch.call(attachment, "SaveAsFile", directory,  "/", fileName);
            }
        }
    }


}
public D2() throws Exception
{
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setBounds(0,0,300,300);
    this.setVisible(true);

    DropTarget dropTarget=new DropTarget();
    dropTarget.setComponent(this);
    dropTarget.addDropTargetListener(new DropTargetAdapter()
            {
                public void drop(DropTargetDropEvent dtde){

                    saveSelectedOutlookMails(DIR);

                }



            });
}


public static void main(String[] args) 

{

    try{

        new D2();
    }catch(Exception e){
        e.printStackTrace();
    }
}

}

The crash

MarkDacek
  • 174
  • 1
  • 10
  • Lets narrow it down. On which line do you get the fatal crash? – Jimmy Smith Oct 20 '14 at 17:03
  • Instantiating explorer. The two prints before that are executed, the one after is not. – MarkDacek Oct 21 '14 at 14:17
  • It looks like the issue may be in how you're accessing the Outlook application. I'm more fluent with VB.NET than Java personally, but [Checkout this prior posting](http://stackoverflow.com/questions/17361340/delete-and-update-outlook-contact-using-jacob-library) – Jimmy Smith Oct 21 '14 at 18:58
  • The same issue is present when using their approach. Do we know whether jacob is compatible with current versions of Java? It's not a typical exception being thrown- it's a Java VM Fatal Error/Exception Access Violation. – MarkDacek Oct 22 '14 at 19:15

2 Answers2

0

Ok, firstly, you are creating Outlook.Application in a way I've never seen before - I've only ever seen the Active X Component way:

e.g.



    ActiveXComponent xl = new ActiveXComponent("Outlook.Application");
    Dispatch explorer = Dispatch.get(xl,"ActiveExplorer").toDispatch();
    Dispatch selection = Dispatch.get(explorer, "Selection").toDispatch();
    Variant count = Dispatch.get(selection, "Count");

    // loop over selected mail items.
    for (int mailIndex = 1; mailIndex <= count.getInt(); mailIndex++ ) {
        Dispatch mailItem = Dispatch.call(selection, "Item", new Variant(mailIndex)).toDispatch();
        Variant subject = Dispatch.get(mailItem, "Subject");
        // .... and so on
    }


Secondly, your code is not saving the mail, its pulling out all the fields and attachments and trying to recreate the mail, which seems inaccurate at best and will only be an approximation of what the message was.

Why don't you just use the COM objects to SaveAs the whole .msg file to disk? Then if you need to access it again you can use something like JDIC to launch Outlook and pop up the message in its original glory, including all attachments?

antsbull
  • 1
  • 2
  • First of all.. thanks very much for your answer. The goal of this is not actually what you would guess it to be, so don't worry too much about what it seems to be doing. I probably should have phrased the question a little differently, but both ways (the ActiveX and the straight Dispatch) cause fatal errors. Do you know whether Jacob is compatible with current versions of Java? Because it's a pretty nasty crash- not your typical exception. – MarkDacek Oct 23 '14 at 13:45
  • We run it in production on Java 6 and 7, on all versions of Windows (XP,2008,Vista,7,8). We only use 32-bit JVMs though. I don't think its necessary, but I always make sure the DLL is loaded explicitly before running any code. – antsbull Oct 23 '14 at 17:19
  • I just ran the first part of your code, using jacob.jar, jacob-1.17-x86.dll and JDK 32-bit 1.7.0_45 and it printed out: com.jacob.com.Dispatch@a4e743 ,false ,explorer – antsbull Oct 23 '14 at 17:32
  • It's definitely loaded: I tried loading it via static{ } and it crashed due to having a duplicate library or something. I keep the .dll in the same directory for ease, at the moment. We're currently using 64-bit JVMs. Do you suppose that would be the issue? – MarkDacek Oct 23 '14 at 17:36
  • It could be the issue, I can't think of any other differences. It might be worth you trying that scenario to at least eliminate it. Our software is used by several hundred users on all versions (32/64) of Windows and on all versions of Outlook from Office 2000 onwards, and we have never had a problem with this code - the only thing we mandate is that our software runs on a 32-bit JVM. – antsbull Oct 23 '14 at 18:06
  • Your screenshot makes it a bit clearer - it is a problem with ntdll.dll, the Windows native API dll. Often this means either that dll is corrupted, or you have a problem with something like a graphics card driver on your machine. When you run the code is it just the code above, or are you doing other things that may involve graphics handling prior to this code being invoked? – antsbull Oct 23 '14 at 21:59
  • I instantiate the Java (note that this class is a JFrame derivative) and drag an email onto it. That's as graphics-related as it gets. – MarkDacek Oct 24 '14 at 17:37
0

My guess is that you are trying to get PROPERTY with name "ActiveExplorer", but it is a method! Here is documentation of that particuliar method https://msdn.microsoft.com/en-us/library/office/ff870017.aspx . Try to use .call() Jacob method to invoke METHODS on MS objects.

jiraspav
  • 41
  • 9