PythonでOutlookを操作してメールを自動化する方法をまとめました。
Outlook操作は敷居が高く感じる方が多いようですが、一つずつ理解すればむしろExcel操作よりも簡単だと思います。
操作の全体感は次の通り。
- ライブラリ等の準備
- メールオブジェクトの作成
- メールオブジェクトの操作
この3つがわかってしまえば、Outlookのメール操作はマスターしたと言っても良いでしょう。
本記事ではPythonでOutlookを使いこなせるようになるために以下の二段構えで解説します。
- 基本的なコードの書き方
- 実践的なコードの書き方
後半は実践的なサンプルコードを掲載しています。ぜひ普段の業務自動化の参考にお使いください。
質問や記事内の誤り、サンプルコード追加のご要望はコメント欄より受け付けております!
【基本編】コードの書き方
win32comライブラリを用いた基本的なコードをご紹介します。
win32comで使われるコードはVBAとほとんど同じです。そのため、「やりたいこと+outlook + VBA」と検索すれば目的のコード(らしきもの)にはたどりつけます。
あと大文字・小文字の区別をするので、その点もお気をつけになってください。
win32comライブラリのインストール
一般的なライブラリ同様、win32comもpip installでインストールできます。
pip install pywin32
コマンドプロンプト上で上記のコードを実行することで、Outlook操作に必要なwin32comライブラリのインストールができます。
なお、冒頭でもご説明の通りwin32comはWindowsのみ対応。MacOS等をお使いの場合はsmtplibなどを使います。
import
import win32com.client
# OutlookAppのインスタンス化
outlook = win32com.client.Dispatch("OutlookApplication")
# NameSpaceオブジェクトのインスタンス化
mapi = outlook.GetNameSpace("MAPI")
Outlook操作のキモとなるのが4行目の「OutlookAppのインスタンス化」です。この後の操作はすべてこのオブジェクトに対して行います。
mapiはメールを保存したり、移動する場合のみ必要になります。送信するだけなら不要です。
フォルダのインスタンス化
# 受信トレイ
inbox = mapi.GetDefaultFolder(6)
# 下書き
draftbox = mapi.GetDefaultFolder(16)
# 送信済み
sentbox = mapi.GetDefaultFolder(5)
GetDefaultFolderの引数に数字を渡すことで、フォルダのインスタンス化ができます。
番号の対応関係はWindowsの公式ドキュメントを参照してください。
フォルダ内のメールリストを取得
# 受信トレイ内
inbox_mailobj_list = inbox.Items
# 下書きフォルダ内
draftbox_mailobj_list = draftbox.Items
# 送信済みトレイ内
sentbox_mailobj_list = sentbox.Items
フォルダ内にあるメールオブジェクトを取得するには、上でご紹介したインスタンス化されたフォルダに.Itemsをつけます。
戻り値はリスト型の”COM Object”です。そのため、個々のメールオブジェクトのプロパティ(件名や本文など)にアクセスするには次の流れになります。
- ループして個々のオブジェクトにアクセス
- プロパティを指定して情報を取得する
やり方は次のセクションで詳しく解説します。
メールオブジェクトからプロパティを取得する
# ループで一つずつ取り出す
for mail_obj in reversed(mail_obj_list):
print(mail_obj.To) # 宛先
print(mail_obj.CC) # CC
print(mail_obj.BCC) # BCC
print(mail_obj.Subject) # 件名
print(mail_obj.Body) # 本文
print(mail_obj.SenderEmailAddress) # 送信者のメールアドレス
逆回転recersedとしたのは、移動を伴う場合にループが失敗することがあるためです。
上記のサンプルコードの場合のようにメールの内容を読み取るだけなら、reverceなしでも問題なしです。
メールを作成する
# メールオブジェクトの作成
mail_obj = outlook.CreateItem(0)
# 宛先
mail_obj.To = "×××@××.co.jp; ooo@ooo.co.jp"
# CC
mail_obj.CC = "×××@××.co.jp"
# BCC
mail_obj.BCC = "×××@××.co.jp"
# 件名
mail_obj.Subject = "××の件"
# 添付
mail_obj.Attachments.Add(file_path)
# 本文/BodyFormat
mail_obj.BodyFormat = 1
mail_obj.Body = "本文が入ります¥n本文が入ります¥n本文が入ります"
メールの作成は、次の2ステップになります。
- メールオブジェクトを作成(2行目)
- プロパティの設定(4行目以降)
メールオブジェクトは、メールを新規作成するときに出てくるウィンドウをイメージすればOKです。
メールオブジェクトの作成直後はまだ何も書かれていないので、件名や本文などのプロパティ設定をします。
必要事項の入力が済んだら、送信したり下書きフォルダに移動するという流れです。
複数のメールアドレスを設定する場合は;(セミコロン)で区切ります。
装飾つきのメールを送る場合
# メールオブジェクトの作成
mail_obj = outlook.CreateItem(0)
# 宛先
mail_obj.To = "×××@××.co.jp"
# CC
mail_obj.CC = "×××@××.co.jp"
# BCC
mail_obj.BCC = "×××@××.co.jp"
# 件名
mail_obj.Subject = "××の件"
# 添付
mail_obj.Attachments.Add(file_path)
# 本文/BodyFormat
mail_obj.BodyFormat = 2
mail_obj.HTMLBody = "本文が入ります<br>本文が入ります<font color="red">本文が入ります</font>"
装飾をつけるには本文をHTMLで書いていきます。
テキストメールとの違いは以下の通り。
- 本文のBodyFormatとして”2″を指定
- 本文にHTMLタグを商品
本文はHTMLで書くので、改行コードは¥nではなく<br>になります。
メールを送信する
# メールを送信する
mail_obj.Send()
重要度の低いメールなら、そのまま送信させてもOKです。
逆に間違いが許されないようなメールなら、下書きフォルダに移動したり、メールを画面表示させるだけに留めるなどするのがおすすめ。
下書きフォルダにメールを移動する
# 下書きフォルダに移動する
mail_obj.Move(draft_folder)
メールの移動には、Moveメソッドの引数にフォルダのインスタンス化の際に作った変数を渡します。
メールの件数が多い場合には、とりあえず下書きフォルダに逃しておくのが良いです。
返信せずに画面表示をする
# 画面表示だけさせる
mail_obj.Display(True)
少ない件数なら、画面に表示だけさせるのも有効です。
送受信
# 受信トレイを送受信する
inbox.Folders.Session.SendAndReceive(True)
# 時間待機(5秒)
import time
time.sleep(5)
SendAndReceiveメソッドは非同期処理なので、送受信が終わる前に次の処理に進んでしまいます。
これでは新着メールを取得できないので、time.sleepで待機時間を入れると良いでしょう。PCのスペックや回線速度が遅い場合は待機時間を長めに取ります。
【実践編】コードの書き方
基本編の内容をふんだんに使ったサンプルコードをご紹介します!
送受信 → メールの内容をDataFrameに格納
import time
import win32com.client
import pandas as pd
# インスタンス化
outlook = win32com.client.Dispatch("OutlookApplication")
mapi = outlook.GetNameSpace("MAPI")
inbox = mapi.GetDefaultFolder(6)
# 受信トレイを送受信
inbox.SendAndReceive()
time.sleep(5)
# 受信トレイ内のメールをすべて取得
inbox_mailobj_list = inbox.Items
# DataFrameに取り込み
mails = []
for mail_obj in inbox_mailobj_list:
mails.append(
{
"件名": mail_obj.Subject,
"本文": mail_obj.Body,
})
df = pd.DataFrame.from_dict(mails, dtype=object)
# 処理済みフォルダを作成する
try:
inbox.Folders.Add(“処理済み”)
except:
pass
# 処理済みフォルダに移動する
for mail_obj in inbox_mailobj_list:
mail_obj.Move("処理済み")
まとめ
実はwin32comで使うコードはVBAとほとんど同じです。
そのため何かわからないことがあった場合には「outlook vba “やりたいこと”」で検索してみてください。これで大抵のことはこれで解決できるはず。
ただしコードは「まったく同じ」とも限らないので、うまく動くまでちょっと試行錯誤は必要。この作業が結構苦労しました。笑
本記事をお読みになられて不具合や疑問点、サンプルコードのご要望がありましたらコメント欄からお知らせいただけると幸いです!