![見出し画像](https://assets.st-note.com/production/uploads/images/86964757/rectangle_large_type_2_5ac1f779aced1fd9e80effca285f555c.png?width=1200)
[Python] Outlookで受信したメールから添付ファイルを指定フォルダに保存する
はじめに
今回は、PythonでOutlookで受信したメールから、添付ファイルを指定フォルダに保存する処理を実装します。
このPythonスクリプトを実行する前提条件としては、PCにOutlookがインストールされている必要があります。
処理概要は、下記です。
受信トレイ内の特定のフォルダにあるメールを取得
受信日が該当月の場合、添付ファイルを特定のフォルダにダウンロードする
ダウンロードしたファイルは、メール受信月を先頭に、次に送信者名のファイル名に設定して、保存する(例:メール受信月が「2022年9月」で、送信者が「AAA株式会社」の場合、「202209_AAA株式会社」)
この処理は、月1回、月末日に実行することを想定しています。
使用するライブラリ
PythonでWindowsのアプリ・ファイルを扱うためのライブラリです。
使用する際には、インストールが必要です。
pip install pywin32
動作環境
windows11
Python 3.10.2
Outlookの設定
メールを取得するOutlookの受信トレイは、受信トレイの中に「領収書」フォルダが存在する構成としています。
![](https://assets.st-note.com/img/1663274455773-NzosSFWHq5.png)
また、領収書として保存したいメールの「領収書」フォルダへのメール移動は、仕分けルールを設定してメールの振り分けを行うよう設定しています。
添付ファイルの保存先のフォルダ構成
メールの受信日の年、月に対応するフォルダに保存していきます。フォルダ構成は、下記です。
\\001_領収書
└─2022
├─202201
├─202202
├─202203
├─202204
├─202205
├─202206
├─202207
├─202208
├─202209
├─202210
├─202211
└─202212
![](https://assets.st-note.com/img/1663274709502-TwGWLS3f0x.png?width=1200)
実装
全体の処理は下記です。
import datetime
import calendar
from pathlib import Path
import win32com.client
SAVE_FOLDER_ROOT = r'H:\xxxxx\001_領収書'
def get_first_day_of_this_month(date: datetime):
return date.replace(day=1)
def get_end_of_this_month(date: datetime):
_, end_day = calendar.monthrange(date.year, date.month)
return date.replace(day=end_day)
def main():
# 実行日より、対象月の月初日、月末日を取得
now = datetime.datetime.now()
start_date = get_first_day_of_this_month(now)
end_date = get_end_of_this_month(now)
# 保存するフォルダ名、ファイル名を作成
year_folder_name = now.strftime('%Y')
year_month = now.strftime('%Y%m')
save_folder_path = Path(SAVE_FOLDER_ROOT) / year_folder_name / year_month
outlook = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI')
inbox = outlook.GetDefaultFolder(6) # 受信トレイ…「6」
recept_folder = inbox.folders['領収書']
# メールを取得
for mail in recept_folder.Items:
received_date = datetime.datetime(mail.ReceivedTime.year ,mail.ReceivedTime.month, mail.ReceivedTime.day, mail.ReceivedTime.hour, mail.ReceivedTime.minute, mail.ReceivedTime.second)
if start_date <= received_date <= end_date:
# 添付ファイルを取得
for attachment in mail.Attachments:
attachment_file = Path(attachment.FileName)
file_name = f'{year_month}_{mail.Sender}{attachment_file.suffix}'
save_file_path = save_folder_path / file_name
if not save_file_path.exists():
attachment.SaveAsFile(save_file_path)
break
if __name__ == '__main__':
main()
順番に処理の内容を説明します。
メールの受信日を絞り込むため、開始日、終了日を算出
処理実行日の月に受信したメールのみ処理対象とするため、絞り込み開始日として、実行日の月の月初日、絞り込み終了日として、実行日の月の月末日を取得します。
get_first_day_of_this_month関数で、月初日を取得します。
月初日の算出は、datetimeモジュールのdatetime.replaceメソッドを使用します。キーワード引数・dayには、月初日の1を設定します。
def get_first_day_of_this_month(date: datetime):
return date.replace(day=1)
get_end_of_this_month関数で、月末日を取得します。
月末日の算出は、calendarモジュールのcalendar.monthrangeメソッドを使用します。
引数に、年、月を渡すと、月初日の曜日と、月の日数がタプルで戻り値として返されます。
そのため、月の日数を関数の戻り値として返します。
def get_end_of_this_month(date: datetime):
_, end_day = calendar.monthrange(date.year, date.month)
return date.replace(day=end_day)
保存先のフォルダ、ファイル名を作成
保存先のフォルダは、メール受信日の年と、年月で保存します。
実行日から年、年月を、datetimeモジュールのdatetime.strftimeメソッドを使用して、日付を文字列に変換します。
次に、ファイルのフルパスを、pathlibモジュールを使用し、Pathオブジェクトを生成し、パスの連結をしています。
year_folder_name = now.strftime('%Y')
year_month = now.strftime('%Y%m')
save_folder_path = Path(SAVE_FOLDER_ROOT) / year_folder_name / year_month
Outlookからメール情報を取得
win32comモジュールを使用し、Outlookからメール情報を取得します。
outlook = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI')
次に、受信トレイのフォルダを取得するには、outlook.GetDefaultFolderメソッドを使用します。
受信トレイを取得する場合、引数には、「6」を指定します。
今回は、受信トレイに「領収書」フォルダを配置しているため、下記のように指定することで、「領収書」フォルダを取得することができます。
inbox = outlook.GetDefaultFolder(6) # 受信トレイ…「6」
recept_folder = inbox.folders['領収書']
それ以外のフォルダを指定する場合、下記を参照ください。
Outlookからメールを取得し、添付ファイルを保存する
「領収書」フォルダ内から、メールを取得します。今回、メール情報としては、下記を取得しています。
受信日時…ReceivedTime
送信者名…Sender
添付ファイル情報…Attachments
受信日時を、datetimeオブジェクトに変換し、該当月の月初日から月末日内に受信したかどうかを判定します。
for mail in recept_folder.Items:
received_date = datetime.datetime(mail.ReceivedTime.year ,mail.ReceivedTime.month, mail.ReceivedTime.day, mail.ReceivedTime.hour, mail.ReceivedTime.minute, mail.ReceivedTime.second)
if start_date <= received_date <= end_date:
対象月に受信したメールの場合、添付ファイルをフォルダに保存します。
Pathlib.existsメソッドを使用し、同一ファイル名が存在しない場合のみ、添付ファイルを保存します。
for attachment in mail.Attachments:
attachment_file = Path(attachment.FileName)
file_name = f'{year_month}_{mail.Sender}{attachment_file.suffix}'
save_file_path = save_folder_path / file_name
if not save_file_path.exists():
attachment.SaveAsFile(save_file_path)
実行結果
該当月に受信したメールに添付されているファイルが保存されるのを確認できました!
![](https://assets.st-note.com/img/1663277976612-vKSUE8tVeo.png?width=1200)
まとめ
今回は、PythonでOutlookで受信したメールから、添付ファイルを指定フォルダに保存する処理について、まとめました。
毎月の定期実行は、WindowsOSのタスクスケジューラを設定しました。下記記事より設定方法ご参照ください。