今回は PyWin32 の Outlook で、特定のフォルダ内にあるすべてのメールが処理できず、半分のメールしか処理できない問題を解決できた忘備録として記事を投稿します。
今回使用するコードと実行例
下書きボックスの中にある python_drafts
に存在するメールをすべて削除済みアイテムボックスの中にある python_deleted
に移動するというソースコードを想定します。
今回の特定のフォルダのメールをすべて移動させることを例に挙げておりますが、移動させることに限らず、フォルダ内のメールすべてに対して~~するという処理に対応します。
import win32com.client
outlook = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI')
draft = outlook.GetDefaultFolder(16) # 16: 下書き
deleted = outlook.GetDefaultFolder(3) # 3: 削除済みアイテム
draft_folders = draft.Folders
deleted_folders = deleted.Folders
def delete_drafts():
Draft_Folder = draft.Folders("python_draft")
Deleted_Folder = deleted.Folders("python_deleted")
i = 1 # カウンタ
for item in Draft_Folder.Items:
print(f"のこり {len(Draft_Folder.Items)} 件: {i} 件目メール破棄しました")
item.Move(Deleted_Folder)
if __name__ == "__main__":
delete_drafts()
実行結果
$ python main.py
のこり 3 件: 1 件目メール破棄しました
のこり 2 件: 2 件目メール破棄しました
本来はメールが3件消えてほしいのですが、2件しか移動されず、どうしても1件残ってしまっています。
原因と対策
項目が頭から順次処理されることにより Draft_Folder.Items
(フォルダ内のメールの集合)が減少するため、半分(奇数の場合は半分-1)のメールが残ってしまいます。そこで、For 文を逆順で回すことによって、Draft_Folder.Items
を頭から処理するのではなく末尾から処理することにより、すべてのメールを削除することが可能になります。
解決したプログラムコード
逆順で処理する(Items コレクションの末尾から処理する)ことによって、特定のフォルダ内のすべてのメールに対して処理を行うことができました。
具体的には、Draft_Folder.Items
を reversed()
関数を用いて reversed(Draft_Folder.Items)
とすることによって逆順の動作を実現しました。
解決したソースコード
import win32com.client
outlook = win32com.client.Dispatch('Outlook.Application').GetNamespace('MAPI')
draft = outlook.GetDefaultFolder(16) # 16: 下書き
deleted = outlook.GetDefaultFolder(3) # 3: 削除済みアイテム
draft_folders = draft.Folders
deleted_folders = deleted.Folders
def delete_drafts():
Draft_Folder = draft.Folders("python_draft")
Deleted_Folder = deleted.Folders("python_deleted")
i = 1 # カウンタ
for item in reversed(Draft_Folder.Items): # ここで reversed 関数を使用する
print(f"のこり {len(Draft_Folder.Items)} 件: {i} 件目メール破棄しました")
item.Move(Deleted_Folder)
if __name__ == "__main__":
delete_drafts()
実行結果
$ python main.py
のこり 3 件: 1 件目メール破棄しました
のこり 2 件: 2 件目メール破棄しました
のこり 1 件: 3 件目メール破棄しました
きちんとすべてのメールが処理されています。
参考文献