はじめに
メールは非同期コミュニケーションです。即時反応を求めるものではありません。とはいえ、ビジネスメールではある程度の期間内には返信が期待されることもあります。
返信が遅いことが予想される相手あてのメールについて、一定期間経過しても返信がなかった場合に、To Doにタスクとして登録するフローを作ってみました。
タスクとして自動登録することで、返信を待っているまま忘れてしまうといったことを防ぐことができるかもしれません。
※Graph APIをあちこち使ってはいますが、プレミアムコネクタは使用していないためOffice 365付属のPower Automateのライセンス範囲内で動作可能です。
使い方/動作イメージ
返信遅くなっては困るメールやいつも返信が遅い相手にメールを送信した時に、送信したメールにカテゴリをあらかじめ準備した分類をセットしておきます。
フローは毎日動作してメールの返信状況を監視します。
指定日数経過しても返信が届いていない場合にTo Doの"タスク"リストに要返信確認のタスクが登録されます。
その後、催促をした結果返信が来た場合タスクを完了します。
スレッドの会話が完了した場合は、スレッドから分類を解除しておきます。
分類を解除していない場合は、スレッドの監視を継続し再び返信の遅延が発生した時にタスクを作成する動作になります。
フロー全体図
フロー解説
1.[Schedule] 繰り返しトリガー
毎朝フローが実行されるように設定しています。
2.[Control]スコープ-パラメータ
フロー内で使用するパラメータを集めてスコープでまとめています。
2-1.[Data Control]作成-CategoryName
Outlookでメールに設定する分類の名前を指定します。
2-2.[Data Control]作成-critical threshold
送信日時(sentDateTime)が現在日時より何日数経過していたら処理対象するかの基準値を定義します。
3.[Variant]変数を初期化する-TargetMails
条件に該当したメールを格納する変数を定義します。
- Name
- TargetMails
- Type
- Array
4.[Control]スコープ-要注意分類のスレッドのconversationIdを取得
指定した分類付きのメールを検索し、メールのスレッドを識別するid(conversationId)を取得します。
4-1.[Office 365 Outlook]HTTP 要求を送信します-要注意分類のメッセージを検索
まず指定の分類が付与されているメールを検索します。Office 365 Outlook コネクタのアクションではすべてのフォルダを対象のに分類を条件としてメールを検索できないので、Graph API を呼び出しています。
この辺りは過去にこちらの記事にまとめています
- URI
- https://graph.microsoft.com/v1.0/me/messages/?$filter=categories/any(i:i eq '@{encodeUriComponent(outputs('作成-CategoryName'))}')
- パラメータで指定した分類をURLエンコードしています。
- メソッド
- GET
- コンテンツの種類
- application/json
4-2.[Data Control]選択-conversationId
分類付きメールのアレイから、メールのスレッドを識別するid(conversationId)のみを抽出します。
- From
- @{body('HTTP_要求を送信します-要注意分類のメッセージを検索')?['value']}
- Map
- conversationId
- @{item()?['conversationId']}
- conversationId
4-3.[Data Control]作成-UniqueなconversationId
4-2の時点では、同じスレッドのメールに分類が設定される場合などにconversationIdが重複した状態の可能性があります。この為、union関数を使って一意なもののみを抽出しています。
- 入力
-
union( body('選択-conversationId'), body('選択-conversationId') )
-
ここまででこのようなconversationIdのアレイが作成できています。
5.[Control]スコープ-スレッドの最新メッセージの送信者が自分のものを抽出
抽出したconversationIdの各メールスレッドの最新のメールの送信者が自分のもの(=返信が来ていないメール)を取得します。
5-1.[Office 365 Users]マイ プロフィールの取得 (V2)
自分のメールアドレスを取得するために使用しています。
5-2.[Control]それぞれに適用する
4.で抽出したconversationIdのメールスレッドごとに処理を繰り返します。
- Select An Output From Previous Steps
- @{outputs('作成-UniqueなconversationId')}
5-2-1.[Office 365 Outlook]HTTP 要求を送信します-指定スレッドのメッセージを取得
Graph APIを使ってconversationIdを条件にスレッドのメールを取得しています。
Graph API のメッセージを取得するエンドポイントを利用します。
- URI
- https://graph.microsoft.com/v1.0/me/messages/?$filter=conversationId eq '@{item()?['conversationId']}'
- メソッド
- GET
- コンテンツの種類
- application/json
5-2-2.[Data Control]作成-latestMail
スレッド内の最新のメールを取得しています。
- 入力
- sort関数で送信日時(snetDateTime)昇順に並び変えたのちに、reverse関数で逆転させて、1つ目のメール(=スレッドで最新のメール)を取得します
-
reverse( sort( body('HTTP_要求を送信します-指定スレッドのメッセージを取得')?['value'], 'sentDateTime' ) )[0]
5-2-3.[Control]条件-スレッドの最新のメールの送信者が自分
最新メールの送信者が自分かどうかで判定します。
- 条件
- AND
- 条件1
- @{outputs('作成-latestMail')?['from/emailAddress/address']}
- is equal to
- @{outputs('マイ_プロフィールの取得_(V2)')?['body/mail']}
5-2-3-1.(True).[Variable]配列変数に追加
5-2-3.の条件を満たしている場合、メールをTargetMails変数に格納します。
- Name
- TargetMails
- Value
- @{outputs('作成-latestMail')}
5-3.[Data Control]アレイのフィルター処理-基準日より古い
ここまでの処理で各スレッド最新のメールで送信者が自分のメールがTargetMails関数に格納されています。送信日付がフロー冒頭のパラメータで指定した基準日より古いメールを抽出します。
- From
- @{variables('TargetMails')}
- Filter Query
- @{item()?['sentDateTime']}
- is less or equal to
- addDays(utcNow(),int(outputs('作成-critical_threshold')))
6.[Control]スコープ-To Doのデフォルトリストのidを取得
タスクを登録する際にリストを指定する必要があります。デフォルトリストのidを取得します。この辺りの解説はこちらの記事にまとめています。
6-1.[Microsoft To Do (Business)]すべての To do リストを一覧表示する (V2)
6-2.[Data Control]アレイのフィルター処理-defaultList
- From
- @{body('すべての_To_do_リストを一覧表示する_(V2)')}
- Filter Query
- @{item()?['wellknownListName']}
- is equal to
- defaultList
6-3.[Data Control]作成-defaultList id
- 入力
- @{body('アレイのフィルター処理-defaultList')[0]?['id']}
7.[Control]スコープ-ToDoにタスク登録
メールをタスクに登録します。
ただし、同じスレッドのメールが既に登録されている場合は、そのタスクを更新することでタスクが増殖しないようにしています。
7-1.[Microsoft To Do (Business)]フォルダー別にTo Doを一覧表示する(V2)
同じスレッドのメールのタスクが登録されているか確認するために、リスト内のタスクをすべて取得します。
- To Do リスト
- @{outputs('作成-defaultList_id')}
- 上から順に取得
- 999
7-2.[Data Control]アレイのフィルター処理-未完了タスクのみ
7-1.で取得したタスクから完了していないものだけを抽出します。完了済みタスクは除外することで、再び返信が滞った場合にタスクとして再登録できるようにしています。
- From
- @{body('フォルダー別に_To_Do_を一覧表示する_(V2)')}
- Filter Query
- @{item()?['status']}
- is not equal to
- completed
7-3.[Control]それぞれに適用する-各スレッドの最新メッセージ
既存のタスクから存在チェックしながらメール1通づつタスクに登録していきます。
- Select An Output From Previous Steps
- @{body('アレイのフィルター処理-基準日より古い')}
7-3-1.[Data Control]作成-TaskKey
タスクの本文にメールスレッドのconversationIdを埋め込むキー情報を生成します。
- 入力
- $$key$$:@{item()?['conversationId']}
7-3-2.[Data Control]アレイのフィルター処理-タスク存在チェック
既存のタスクに同じスレッドのタスクが存在しないかをチェックします。
このフローで作成したタスクは本文に7-3-1のキー情報を埋め込んでいるため、この値の有無でチェックすることができます。
- From
- @{body('アレイのフィルター処理-未完了タスクのみ')}
- Filter Query
- @{item()?['body/content']}
- contains
- @{outputs('作成-TaskKey')}
7-3-3.[Control]条件-タスクがない場合は新規、あれば更新
7-3-2の出力の数で処理を分岐します。
- 条件
- AND
- 条件1
-
length(body('アレイのフィルター処理-タスク存在チェック'))
- is equal to
- 0
-
7-3-4.(Yes).[Microsoft To Do (Business)]To Doを追加する(V3)
メールの情報を基にタスクを追加します。
- To Doリスト
- @{outputs('作成-defaultList_id')}
- タイトル
- 【📧返信要確認】@{items('それぞれに適用する-各スレッドの最新メッセージ')?['Subject']}
- 期日
- ※すでに遅延した時点でタスク登録するため期日は+1日にしています。
-
addDays(utcNow(),1)
- リマインダー日時
- ※すでに遅延した時点でタスク登録するため翌日の9時にしています。
-
convertFromUtc( addDays(utcNow(),1), 'Tokyo Standard Time', 'yyyy-MM-ddT00:00:00' )
- 重要度
- high
- 本文コンテンツ
- キー情報とOutlook on the Webのメールリンクを本文にセットします。
-
@{outputs('作成-TaskKey')} @{item()?['webLink']}
- リマインダーをオンにする
- はい
7-3-5.(No).[Microsoft To Do (Business)]To Doを更新する(V2)
メールの情報を基にタスクを更新します。
- To Doリスト
- @{outputs('作成-defaultList_id')}
- タイトル
- 【📧返信要確認】@{items('それぞれに適用する-各スレッドの最新メッセージ')?['Subject']}
- 重要度
- high
- 本文コンテンツ
- キー情報とOutlook on the Webのメールリンクを本文にセットします。
-
@{outputs('作成-TaskKey')} @{item()?['webLink']}
制限事項的なもの
- Outlook on the Webまたは新しいOutlook デスクトップアプリを想定しています。(従来の?)Outlook デスクトップアプリを使っていないのでどのような動作になるかわかりません
- Outlook on the Webの設定で「メールをスレッドごとにグループ化」としている状態で使うことを想定しているフローです
- このパラメータによりメールに分類を付与した時の動作が変わります
- メールをスレッドごとにグループ化→スレッドのメール全体に分類が付与される
- メールを個別のメッセージとして表示→選択したメール単体に分類が付与される
さいごに
To Doに返信を催促するタスクを追加するという動作にしましたが、やろうと思えば催促メールを自動送信することも可能です。相手との関係性を踏まえて返信メッセージを生成AIにつくらせるというのも面白そうです。