Windows 環境+Outlook が入っている方向けの記事です。
win32com を使えば、メール送受信・仕分け・添付ファイル保存・予定の作成・タスク管理など、かなりの範囲を Python から自動化できます。
本記事ではその方法をご紹介します。
- 1. 事前準備(環境・基本構造)
- 2. Outlook.Application と MAPI 名前空間
- 3. フォルダ操作(Inbox / サブフォルダなど)
- 4. メール送信(MailItem)
- 5. 添付ファイルの追加・受信側の保存
- 6. 受信メールの取得・検索・フィルタ
- 7. メールの状態変更・移動・削除
- 8. メール本文の取得・解析
- 9. 予定表(AppointmentItem)の操作
- 10. 連絡先(ContactItem)の操作
- 11. タスク(TaskItem)の操作
- 12. ルールに近いことを Python で代用する
- 13. エラーハンドリングと注意点
- まとめ:Outlook も win32com でガッツリ自動化できる
1. 事前準備(環境・基本構造)
Python から Outlook を操作する準備
Outlook 用でも Excel と同じく pywin32 を使います。
pip install pywin32基本の雛形はこんなイメージです。
from win32com.client import Dispatch, constants
def open_outlook():
outlook = Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")
return outlook, namespace
def quit_outlook(outlook):
# Outlook 自体を終了させたくない場合は、通常ここは呼ばない
# outlook.Quit() するとアプリ自体が閉じる
outlook.Quit()Outlook は普段から起動したまま使うことが多いので、Quit() はあえて呼ばずに、Python スクリプト側だけ終了させるパターンも多いです。
2. Outlook.Application と MAPI 名前空間
Outlook.Application を取得する
通常はこれで OK です。Outlook が起動していなければ起動されます。
from win32com.client import Dispatch
outlook = Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")既存インスタンスに接続する(GetObject)
すでに起動している Outlook にぶら下がりたい場合。
from win32com.client import GetObject
outlook = GetObject(Class="Outlook.Application")
namespace = outlook.GetNamespace("MAPI")プロファイルを指定してログオンする
Exchange や複数プロファイルを使っている場合は Logon を明示することがあります。
namespace.Logon(
Profile="Outlook", # プロファイル名(Outlook 側の設定)
ShowDialog=False,
NewSession=False,
)既定のストア(メールボックス)を取得する
store = namespace.DefaultStore
print(store.DisplayName) # 「あなたの名前」など
root_folder = store.GetRootFolder()3. フォルダ操作(Inbox / サブフォルダなど)
既定のフォルダ(受信トレイ・送信済みなど)を取得する
GetDefaultFolder に定数を渡します。
from win32com.client import constants
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
sent = namespace.GetDefaultFolder(constants.olFolderSentMail)
drafts = namespace.GetDefaultFolder(constants.olFolderDrafts)
calendar = namespace.GetDefaultFolder(constants.olFolderCalendar)
contacts = namespace.GetDefaultFolder(constants.olFolderContacts)
tasks = namespace.GetDefaultFolder(constants.olFolderTasks)サブフォルダを取得する
# 受信トレイ配下の「請求書」フォルダ
invoice_folder = inbox.Folders("請求書")フォルダを列挙する
def print_folders(folder, level=0):
indent = " " * level
print(indent + folder.Name)
for sub in folder.Folders:
print_folders(sub, level + 1)
root = namespace.DefaultStore.GetRootFolder()
print_folders(root)サブフォルダを作成・削除する
# 受信トレイ配下に「スクリプト用」フォルダを作成
new_folder = inbox.Folders.Add("スクリプト用")
# 削除
new_folder.Delete()4. メール送信(MailItem)
シンプルなテキストメールを送る
outlook, namespace = open_outlook()
mail = outlook.CreateItem(constants.olMailItem)
mail.To = "example@example.com"
mail.Subject = "テストメール"
mail.Body = "Python + win32com からのテストメールです。"
mail.Send()宛先・CC・BCC を指定する
mail = outlook.CreateItem(constants.olMailItem)
mail.To = "to1@example.com; to2@example.com"
mail.CC = "cc1@example.com"
mail.BCC = "bcc1@example.com"
mail.Subject = "CC/BCC テスト"
mail.Body = "CC と BCC を使ったサンプルです。"
mail.Send()HTML メール(HTMLBody)を送る
html = """
<html>
<body>
<h1>Python からの HTML メール</h1>
<p>これは <b>太字</b> のサンプルです。</p>
</body>
</html>
"""
mail = outlook.CreateItem(constants.olMailItem)
mail.To = "example@example.com"
mail.Subject = "HTML メールのテスト"
mail.HTMLBody = html
mail.Send()既定の署名を使いたい場合の簡易テクニック
Outlook の既定署名をそのまま利用するには、一度 Display() してから HTMLBody を加工する方法がよく使われます。
mail = outlook.CreateItem(constants.olMailItem)
mail.To = "example@example.com"
mail.Subject = "署名付きメール"
# 署名付きの空メールを表示させる
mail.Display()
# 既に署名が入った HTMLBody の先頭に本文を追加
body = "<p>本文です。署名の前に追加されます。</p>"
mail.HTMLBody = body + mail.HTMLBody
# そのまま人間が送信ボタンを押しても良いし、自動送信も可
# mail.Send()5. 添付ファイルの追加・受信側の保存
メール送信時に添付ファイルを追加する
mail = outlook.CreateItem(constants.olMailItem)
mail.To = "example@example.com"
mail.Subject = "添付ファイルのテスト"
mail.Body = "ファイルを添付しています。"
file_path = r"C:\path\to\report.xlsx"
mail.Attachments.Add(Source=file_path)
mail.Send()受信メールの添付ファイルを保存する
import os
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
messages = inbox.Items
save_dir = r"C:\path\to\download_attachments"
for msg in messages:
# 添付がない場合もあるのでチェック
if msg.Attachments.Count > 0:
for i in range(1, msg.Attachments.Count + 1):
attachment = msg.Attachments(i)
filename = attachment.FileName
save_path = os.path.join(save_dir, filename)
attachment.SaveAsFile(save_path)
print("Saved:", save_path)6. 受信メールの取得・検索・フィルタ
受信トレイの最新メールを取得する
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
items = inbox.Items
items.Sort("[ReceivedTime]", True) # True で降順(新しい順)
latest = items.GetFirst()
print(latest.Subject, latest.ReceivedTime)条件付きでメールを取得(Restrict を使う)
Restrict は Outlook 側のフィルタ機能で、高速に抽出できます。
from datetime import datetime, timedelta
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
items = inbox.Items
# 直近 1 日以内のメール
yesterday = datetime.now() - timedelta(days=1)
criteria = "[ReceivedTime] >= '" + yesterday.strftime("%m/%d/%Y %H:%M %p") + "'"
filtered = items.Restrict(criteria)
for msg in filtered:
print(msg.Subject, msg.ReceivedTime)※ 日付フォーマットは Outlook 依存があるので、うまく動かない場合はローカル設定に合わせて調整が必要なことがあります。
件名や送信者でフィルタする(単純な例)
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
items = inbox.Items
# 件名に「請求書」を含むメールのみ
matched = [m for m in items if "請求書" in (m.Subject or "")]
for msg in matched:
print(msg.Subject, msg.SenderName)(これは Python 側でフィルタしている例なので件数が多いと遅いです。できれば Restrict や Find を使うほうが高速です。)
Find / FindNext を使った検索
items = inbox.Items
item = items.Find("[Subject] = '特別なお知らせ'")
while item is not None:
print("Found:", item.Subject, item.ReceivedTime)
item = items.FindNext()7. メールの状態変更・移動・削除
既読/未読を切り替える
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
items = inbox.Items
for msg in items:
if not msg.UnRead:
continue
# 未読メールだけ既読にする
msg.UnRead = False
msg.Save()フォルダにメールを移動する
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
target_folder = inbox.Folders("スクリプト用")
items = inbox.Items
for msg in list(items): # 途中でコレクションが変わるので list() でコピー
if "請求書" in (msg.Subject or ""):
moved = msg.Move(target_folder)
print("Moved:", moved.Subject)メールを削除する
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
items = inbox.Items
for msg in list(items):
if "[自動削除]" in (msg.Subject or ""):
msg.Delete()カテゴリを設定する
Outlook の「カテゴリ」機能に色ラベルが付いている場合。
msg.Categories = "Python処理" # Outlook 側に存在するカテゴリ名
msg.Save()フラグを設定する(フォローアップ)
msg.FlagRequest = "フォローアップ"
msg.FlagStatus = constants.olFlagMarked
msg.Save()8. メール本文の取得・解析
テキスト本文(Body)を取得する
msg = inbox.Items.GetFirst()
print(msg.Subject)
print(msg.Body)HTML 本文(HTMLBody)を取得する
html = msg.HTMLBody
print(html)正規表現で金額・日付を抽出する簡単な例
import re
body = msg.Body or ""
amount_match = re.search(r"(\d{1,3}(?:,\d{3})*)(円|JPY)", body)
if amount_match:
amount = amount_match.group(1)
print("検出金額:", amount)9. 予定表(AppointmentItem)の操作
予定を新規作成する
from datetime import datetime, timedelta
outlook, namespace = open_outlook()
calendar = namespace.GetDefaultFolder(constants.olFolderCalendar)
appt = outlook.CreateItem(constants.olAppointmentItem)
appt.Subject = "Python で作成した予定"
appt.Location = "会議室 A"
start = datetime(2025, 11, 20, 10, 0)
end = start + timedelta(hours=1)
appt.Start = start
appt.End = end
appt.Body = "これは Python スクリプトから作成された会議です。"
appt.ReminderMinutesBeforeStart = 15
appt.BusyStatus = constants.olBusy
appt.Save() # 予定表に保存
# appt.Display() # 画面で確認したいとき参加者を招待する(会議として送信)
meeting = outlook.CreateItem(constants.olAppointmentItem)
meeting.MeetingStatus = constants.olMeeting
meeting.Subject = "Python 勉強会"
meeting.Location = "オンライン"
meeting.Start = datetime(2025, 11, 21, 19, 0)
meeting.Duration = 90 # 分
recipient = meeting.Recipients.Add("guest@example.com")
recipient.Type = 1 # 必須参加(olRequired)
meeting.Body = "Python + Outlook 自動化の勉強会です。"
meeting.Send() # 招待メールを送る予定表から予定を取得・検索する
calendar = namespace.GetDefaultFolder(constants.olFolderCalendar)
items = calendar.Items
items.Sort("[Start]")
items.IncludeRecurrences = True
start = datetime(2025, 11, 1)
end = datetime(2025, 11, 30)
restriction = f"[Start] >= '{start:%m/%d/%Y %H:%M %p}' AND [End] <= '{end:%m/%d/%Y %H:%M %p}'"
filtered = items.Restrict(restriction)
for appt in filtered:
print(appt.Subject, appt.Start, appt.End)10. 連絡先(ContactItem)の操作
新しい連絡先を作成する
contacts_folder = namespace.GetDefaultFolder(constants.olFolderContacts)
contact = outlook.CreateItem(constants.olContactItem)
contact.FullName = "山田 太郎"
contact.Email1Address = "taro.yamada@example.com"
contact.CompanyName = "ヤマダ株式会社"
contact.MobileTelephoneNumber = "090-1234-5678"
contact.JobTitle = "営業"
contact.Save()連絡先を列挙する
for item in contacts_folder.Items:
print(item.FullName, item.Email1Address)11. タスク(TaskItem)の操作
タスクを新規作成する
tasks_folder = namespace.GetDefaultFolder(constants.olFolderTasks)
task = outlook.CreateItem(constants.olTaskItem)
task.Subject = "レポート提出"
task.Body = "金曜日までに営業レポートをまとめる"
task.DueDate = datetime(2025, 11, 22)
task.Importance = constants.olImportanceHigh
task.Save()タスクを一覧取得する
for t in tasks_folder.Items:
print(t.Subject, t.DueDate, t.Status)タスクを完了にする
for t in tasks_folder.Items:
if t.Subject == "レポート提出":
t.MarkComplete()
t.Save()12. ルールに近いことを Python で代用する
Outlook の「受信トレイルール」を直接いじるのは複雑なので、
- Python スクリプトを定期実行(タスクスケジューラなど)
- 条件に合うメールを検索してフォルダに移動する
という形で「自作ルール」を実装するのが現実的です。
件名に「請求書」を含むメールを自動で移動
from datetime import datetime, timedelta
outlook, namespace = open_outlook()
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
target_folder = inbox.Folders("請求書")
items = inbox.Items
items.Sort("[ReceivedTime]", True)
# 直近 3 日分だけチェックしてフォルダに移動
limit = datetime.now() - timedelta(days=3)
criteria = "[ReceivedTime] >= '" + limit.strftime("%m/%d/%Y %H:%M %p") + "'"
recent = items.Restrict(criteria)
for msg in list(recent):
if "請求書" in (msg.Subject or ""):
msg.Move(target_folder)13. エラーハンドリングと注意点
try / finally で安全に扱う
from win32com.client import Dispatch, constants
outlook = None
try:
outlook = Dispatch("Outlook.Application")
namespace = outlook.GetNamespace("MAPI")
inbox = namespace.GetDefaultFolder(constants.olFolderInbox)
# ここに処理を書く
msg = inbox.Items.GetFirst()
print(msg.Subject)
except Exception as e:
print("エラー:", e)
finally:
# Outlook を閉じたくない場合は何もしない
# outlook.Quit() するとアプリ自体が終了する
passセキュリティ警告について
一部環境では、プログラムからのメール送信や連絡先アクセス時に Outlook のセキュリティ警告 が出ることがあります(ウイルス対策ソフトの設定や Outlook のバージョンに依存)。
- セキュリティ設定で「自動承認」を許可する
- 会社環境では情報システム部門のポリシーに従う
などの対応が必要になる場合があります。
まとめ:Outlook も win32com でガッツリ自動化できる
ここまでで、
Outlook.ApplicationとMAPI名前空間の基本- メールの送信(テキスト・HTML・添付)
- 受信メールの取得・検索・既読/移動/削除・カテゴリ/フラグ
- 添付ファイルの一括保存
- 予定表(AppointmentItem)・会議招待
- 連絡先(ContactItem)・タスク(TaskItem)
- 疑似ルールによる自動仕分け
といった、実務で使いそうな操作を一通り押さえました。
実務的には、
- フォルダをきちんと分ける
- 定型処理(請求書の仕分け、添付の保存、定例会議の作成など)をスクリプト化
- Windows タスクスケジューラなどで定期実行する
という流れにすると、「Outlook の定期ルーチンを全部 Python に任せる」ことができます。

コメント