2020年7月13日 星期一

使用 JACOB Java-COM Bridge 操作 Microsoft Outlook

Java 無法直接執行作業系統的部份函式庫,
例如無法直接執行並操作如 Microsoft Outlook, Word, Excel 等跟作業系統綁的較緊的軟體,
如果真得要使用 Java 來操作,
則必須要使用例如 JNI 或 Java-COM Bridge 等技術 (例如 JACOB, Jawin 等)來實現。

Java Outlook Connector 是一個提供 Java 控制本地端 Outlook 的 Java Lib,
將底層的 JNO、 COM、MAPI 等複雜的實現進行了封裝,
不過只有試用版 (每次執行都會跳出建議購買的視窗) 及付費版。

這裡要介紹的是另一個方案, JACOB,
為一個免費的 Java-COM Bridge ,
這邊要演示的是使用 JACOB 這個 Java-COM Bridge 來操作 Outlook 的範例。
要注意的是,這裡只是直接操作電腦上的 Outlook 軟體,
並非使用 JavaMail 來連接 mail server,
所以並不需要進行登入連接等動作,
可以想成類似直接使用 VBscript 來控制 Outlook。

首先先去 JACOB 官網下載所需的 JAR 檔和 DLL 檔,
裡面有提供最新版放在 Sourceforge.net 上的檔案下載頁面連結
下載完解壓縮後可以看到所需的 jacob.jar、jacob-1.19-x64.dll  (或著是 32 位元,依執行環境自行選擇),也有附上 Javadoc 的說明文檔。

引入 jacob.jar、jacob-1.19-x64.dll  (例如設定環境變數 path、或放到System32 資料夾下、或放到程式同目錄等,
可參考
source of com.jacob.com.LibraryLoader
System.loadLibrary() 的使用方法彙總
) 後,
就可以開始撰寫程式。

範例程式碼如下,
其中讀取了 Outlook 的 INBOX 收件夾,
找出特定 Subject 的信,並將信上的附件檔存到本地資料夾。

package outlookReaderTest;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;

public class JacobTest {

 public static void main(String[] args) {
  // 指定 INBOX 收件夾,參考 https://docs.microsoft.com/zh-tw/office/vba/api/outlook.oldefaultfolders
  int olFolderInbox = 6; 
  ActiveXComponent outlookApplication = new ActiveXComponent("Outlook.Application");
  Dispatch outlookObject = outlookApplication.getObject();
  Dispatch myNamespace = Dispatch.call(outlookObject, "GetNamespace","MAPI").toDispatch();
  Dispatch myFolder = Dispatch.call(myNamespace,"GetDefaultFolder", Integer.valueOf(olFolderInbox)).toDispatch();
  Dispatch mails = Dispatch.get(myFolder, "Items").toDispatch();
  
  /*
   * 上述程式碼等同於 VBscript 的:
   * Dim outlookObject, myNamespace, myFolder, mails
   * Set outlookObject = CreateObject("Outlook.Application")
   * Set myNamespace = outlookObject.GetNamespace("MAPI")
   * Set myFolder = myNamespace.GetDefaultFolder(6)
   * Set mails = myFolder.Items
   * 下面的程式碼跟 VBscript 的對照可以此類推
   */

  int count = Dispatch.call(mails, "Count").getInt();
  System.out.println("Total Mail Count: " + count);
  for (int i = 1; i <= count; i++)
  {
   Dispatch mail = Dispatch.call(mails, "Item", Integer.valueOf(i)).toDispatch();
   String subject = Dispatch.call(mail, "Subject").getString();
 
   if ("This is a test mail".equals(subject)) {
    System.out.println(i);
    System.out.println(subject);
    
    String saveFolderPath = "D:\\tempTestFoler";
    
    //Save attachments
    Dispatch attachs = Dispatch.call(mail, "Attachments").toDispatch();
    int attachCount = Dispatch.call(attachs, "Count").getInt();
    System.out.println("attachCount: " + attachCount);
    for (int j = 1; j <= attachCount; j++) {
     Dispatch attach = Dispatch.call(attachs, "Item", Integer.valueOf(j)).toDispatch();
     String attachName = Dispatch.call(attach, "FileName").getString();     
     Dispatch.call(attach, "SaveAsFile", saveFolderPath + "\\" + attachName);
     System.out.println(attachName + " -- saved");
     //Dispatch.call(mail, "Delete");
    }
   }
  }
 }

}





參考:

  1. Open source java library to read outlook emails, calendar etc
  2. 【JACOB】Java-COM Bridge 介紹
  3. COM - Microsoft物件導向開發架構的基礎
  4. Java Outlook Connector