LoginSignup
6
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-12-10

ブログ記事からの移行

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

背景

Outlook のメールを org-mode の TODO に連携させる の改良版。

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

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

方針

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

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

手順

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

コード

Outlook側

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

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

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に送れるようになる。

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側

前回と同じスクリプト

;; 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の設定。必要に応じてカスタマイズ。

(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 なんかで無理やりやってもいいけど。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6