Outlook のメールから org-mode の TODO に登録する

[ブログ記事からの移行](http://ichiroc.hatenablog.com/entry/2013/11/18/075654)

Emacs + Windows + Outlook というエンタープライズな環境でEmacsを使用しているニッチな人のための面白拡張。

### 背景
[Outlook のメールを org-mode の TODO に連携させる](http://ichiroc.hatenablog.com/entry/2013/10/22/210520) の改良版。

前回は直接アジェンダファイルを更新していたが、org-protocolを利用すると、よりスマートに対応出来る。

- アジェンダファイルを再読込しなくても、更新が反映される
- 手元での更新と、Outlookからの更新で衝突が無い
- 書き出すテンプレートを簡単に設定出来る

### 方針
Outlook からの更新は org-protocol を使用して行う。

- Outlookにマクロを登録して、メール画から簡単にEmacsに送れるようにする
- org-mode上で、Outlookのメールにリンクして直接開けるようにする

### 手順

- org-protocolをダウンロード
    - list-package から org-protocol-jekyll を使用する(自分はどっかから落としてきた) [ここ](https://github.com/vonavi/org-protocol-jekyll)だっけかな？
- Windowsに```org-protocol:/```を関連付けする
- Emacsでorg-protocolを受け取れるようにする

### コード

#### Outlook側

Outlookのマクロに以下を登録。
メール画面からWriteToOrgFileマクロを呼び出すと実行される。
クイックアクセスツールバーにマクロを登録しておくと Alt+1 等で呼び出せて便利。

ちなみにスクリプトでは自動的に本文をクリップボードにコピーする。

```vbnet
Sub WriteToOrgFile()
    ' コピペスピードアップの為、最初にIEオブジェクトを生成
    Set objIE = CreateObject("InternetExplorer.Application")
    Dim mail As MailItem
    Set mail = ActiveExplorer.Selection.Item(1)
    
    Dim wshell
    Set wshell = CreateObject("WScript.Shell")
    Call objIE.navigate("about:blank")
    objIE.document.Body.innerText = mail.Body

    ' JS の encodeURI を使用する
    Dim sc
    Set sc = CreateObject("ScriptControl")
    sc.Language = "JScript"
    
    Dim js
    Set js = sc.CodeObject
    
    Subject = js.encodeURI(mail.Subject)
    Subject = Replace(Subject, "[", "「")
    Subject = Replace(Subject, "]", "」")
    
    'Subject = Replace(Subject, " ", "%20")
    Subject = Replace(Subject, "/", "%2F")
    'org-protocol:/capture:/x/outlook:$MailEntryId/$MailSubject/"  の形式でURLが実行される
    captureUrl = "org-protocol:/capture:/x/outlook:" & mail.EntryID & "/" & Subject & "/"

    ' 本文をクリップボードに格納して、後で利用出来るように非同期で実行する
    ' 事前にコピーすると capture によってクリップボードがリンクで上書きされる
    Call wshell.Run(captureUrl)
    
    ' 必要に応じて本文を使用出来るようにクリップボードにコピーする
    Body = Replace(mail.Body, vbCrLf, Chr(10))
    Body = js.encodeURI(Body)
    Call copyText(mail.Body, objIE)
End Sub

Private Sub copyText(text, objIE)
    OLECMDID_COPY = 12
    OLECMDID_SELECTALL = 17
    If objIE Is Nothing Then
        Set objIE = CreateObject("InternetExplorer.Application")
        Call objIE.navigate("about:blank")
        objIE.document.Body.innerText = text
    End If
    Call objIE.execWB(OLECMDID_SELECTALL, 0)
    Call objIE.execWB(OLECMDID_COPY, 0)
    Call objIE.Quit
End Sub

```

#### レジストリ側
これを登録すると、 ```org-protocol:/``` の形式のURLをEmacsに送れるようになる。

```registry
REGEDIT4

[HKEY_CLASSES_ROOT\org-protocol]
@="URL:Org Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\org-protocol\shell]
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
@="\"C:\\tools\\emacs\\bin\\emacsclientw.exe\" \"%1\""
```
Emacsのパスは環境に合わせて変える。

#### Emacs側

前回と同じスクリプト

```lisp
;; outlook 形式のURLを開く
;; see http://lists.gnu.org/archive/html/emacs-orgmode/2008-08/msg00172.html
(defun org-open-outlook-url (uid)
  "Open an outlook format url"
  (interactive "sGUID: ")
  (w32-shell-execute nil (format "outlook:%s" uid)))
(org-add-link-type "outlook" 'org-open-outlook-url)

;; org-protocol
;; see http://orgmode.org/worg/org-contrib/org-protocol.html
(require 'org-protocol)

```

CaptureのTemplateの設定。必要に応じてカスタマイズ。

```lisp
(add-to-list 'org-capture-templates (quote ( ("x" "From external" entry (file+headline (concat my-project-directory "org/tasks.org") "*Task Stuck*") "* ACTN %?%a   :outlook:
  :PROPERTIES:
  :CREATED_AT: %U
  :END:
  %c
  %i" :empty-lines 1 t TODO))))

```

### 課題

org-protocolはemacsclientを使用してURLをEmacsに送る。
実行後、何故かemacsclientのプロセスが残ってしまう。
メモリなどは影響が無いが、気持ち悪い。

### まとめ


前回より大分スマートになった。
あとはプロセスが自動的に消えれば完璧なんだけど・・。 
```taskkill``` なんかで無理やりやってもいいけど。