fum125’s diary

IT全般に関する技術メモなど

Outlook2016 を Python から制御してみる (6)

さて、今回は作成した python スクリプトを呼び出してみたいと思います。

作成するスクリプトについて

次のような動きをするスクリプトを作ってみます。

(1) まず、outlook 上でメールを選択しておきます。
(2) リボン上に用意したボタンをクリックします。
(3) ボタンに割り付けたアクションとして、「マクロ」を実行します。
(4) マクロから、今回作成する Phthon スクリプトを実行します。
(5) ここから Python 本体の処理。
  (5-1) Outlook 上で選択されているメールの一覧を調べます。
  (5-2) 各メールの送信日付を調べます。
  (5-3) "アーカイブ" というフォルダを作り、年月ごとにファイルを移動します。

f:id:fum125:20180615233820p:plain

では、ステップバイステップで作ってみます。

アーカイブ場所を作る

アーカイブ場所はどこでも良いのですが、今回は "Archive.pst" を作って、ここに保存するようにします。
あらかじめ、Outlook から [ファイル] - [情報] - [アカウント設定] と進み、 "Archive" という名前のデータファイルを新規に作っておきました。

f:id:fum125:20180616084548p:plain

Outlook のフォルダに "Archive" が作られました。

f:id:fum125:20180616110553p:plain

python スクリプトを作る

次に、pythonスクリプトを先に作ってみます。

まずはお決まりの宣言から
import win32com.client

win32 = win32com.client.Dispatch('Outlook.Application')
mapi = win32.GetNamespace('MAPI')

これで、Outlook にアクセスするための MAPI を取りました。

選択されているメールの一覧を取得する

次に、現在選択されているメールの一覧を取得してみます。
対象は1個のメールだけではなく、複数選択されていても大丈夫です。

デバッグとして、取得できたメール一覧のサブジェクトも表示してみます。

# 選択されているメールの一覧を、リスト形式で取得する。
items = win32.ActiveExplorer().Selection

# 順番にサブジェクトを表示してみる。
for item in items:
    print(item.Subject)

「いま選択されているメール」は、MAPI ではなく、win32 の方から取得できました。

対象メールの送信日付を調べる。

送信日付は、CreationTIme で取得できました。
先ほどの for ループ内で、作成年月を取ってきます。

for item in items:
    ctime = item.CreationTime
    print('create time => %d / %d' % (ctime.year, ctime.month))
アーカイブフォルダ配下に、年月フォルダを作成する。

アーカイブフォルダは、事前に MAPI を使って取得しておきます。

# メール保存先を用意しておく。
archFolder = mapi.Session.Folders['Archive']

先ほどの for ループの延長です。
アーカイブフォルダ配下に "年_月" という名前のフォルダを作ります。

for item in items:
    ctime = item.CreationTime
    print('create time => %d / %d' % (ctime.year, ctime.month))
    
    # メール保存先を決定する。なければ作成する。
    des = '%d_%d' % (ctime.year, ctime.month)
    try:
        desFolder = archFolder.Folders[des]
    except:
        desFolder = archFolder.Folders.Add(des)
メールを移動する

対象メールを、アーカイブ配下の "年_月" フォルダに移動します。

    item.Move(desFolder)
ちょっと修正

ひとまずこれで動くようになりましたが、もしかしたら items はリストの後ろから処理するほうがいいのかもしれません。

for item in reversed(items):
完成

ここまでで、python スクリプトは完成です。
まとめると、こんな感じです。

import win32com.client

win32 = win32com.client.Dispatch('Outlook.Application')
mapi = win32.GetNamespace('MAPI')

# メール保存先を用意しておく。
archFolder = mapi.Session.Folders['Archive']


# 選択されているメールの一覧を、リスト形式で取得する。
items = win32.ActiveExplorer().Selection

# 順番にサブジェクトを表示してみる。
for item in reversed(items):
    ctime = item.CreationTime
    print('create time => %d / %d' % (ctime.year, ctime.month))
    
    # メール保存先を決定する。なければ作成する。
    des = '%d_%d' % (ctime.year, ctime.month)
    try:
        desFolder = archFolder.Folders[des]
    except:
        desFolder = archFolder.Folders.Add(des)

    item.Move(desFolder)

pythonを実行するマクロを用意する

Outlook でマクロが使えるようになるには、自己証明書を用意したり、いろいろと面倒な手続きがあります。
そのあたりの手順は別の機会で。

今回は、自作したPythonスクリプトを呼び出す Outlook マクロを呼び出すところから紹介します。

Outlook マクロを "Public Sub ~" で宣言して、適当な名前の関数を用意します。
関数の引数はありません。

Public Sub Archive_Mail()

End Sub

この関数の中に、python を実行するコマンド行を記述します。

Public Sub Archive_Mail()
    With CreateObject("Wscript.Shell")
        .Run "C:\annaconda3\python.exe D:\work\Archive_Mail.py", 5
    End With
End Sub

WSH の Run() の引数に "5" を指定していますので、上記の場合は動作確認用に、コマンドプロンプトの黒い画面が現れます。
この WSH のメソッド解説や引数の意味は atmarkit さんの記事が詳しかったので、ご参照ください。
http://www.atmarkit.co.jp/ait/articles/0407/08/news101_2.html

マクロを呼び出すボタンを作る

いよいよ最後のステップです。

Outlook 画面のリボンの適当な場所を右クリックし、[リボンのユーザ設定...] を選びます。

f:id:fum125:20180617215030p:plain

リボンのユーザー設定画面が表示されたら、コマンドの選択で [マクロ] に絞り込み、先ほど作成したマクロを選択します。

次に リボンのユーザ設定から、ボタンを配置したい場所を選びます。

最後に [追加>>] をクリックして終了です。

f:id:fum125:20180617220138p:plain

最後に

以上ですべての準備が終わりました。

Outlook 上のメールを選択 (複数選択も可) し、リボン上のボタンをクリックすると、
メールが Archive フォルダに年月に分類保存されます。