OutlookのGraph APIを用いて、自分がメンションされたメールを一覧化する【Power Automate】

`Outlook`、`Teams`、その他でメンション、絶え間ない通知に、おぼれかけている毎日。
`Power Automate`では
 - [自分が @mentioned である場合](https://learn.microsoft.com/ja-jp/Connectors/teams/#@mentioned-%E3%81%AE%E5%A0%B4%E5%90%88)
 - [自分をメンションした新しいメールが届いたとき (V3)](https://learn.microsoft.com/ja-jp/power-automate/email-triggers?tabs=classic-designer)

という便利なトリガーも存在するため、こちらでメンションをストックすることもできそうです。

https://learn.microsoft.com/ja-jp/Connectors/teams/#@mentioned-%E3%81%AE%E5%A0%B4%E5%90%88

https://learn.microsoft.com/ja-jp/power-automate/email-triggers?tabs=classic-designer

しかしながら、メンションがつく度に、**何かしらのツールにデータがストックされるのも少し邪魔・・・。**
どちらかというと決まったタイミングで、自分が必要な分だけ集めたい・・・

ということから、**Outlookのメールに焦点を宛て、自分がメンションされたメールを一覧化する方法を模索してみました。**

# メンションされた通知を一覧化する
前述した通り、Teams、Outlookそれぞれメンションされた投稿やメッセージを受信する都度、発火するトリガーは、前述のとおり、すでに存在します。

しかしそういったものも、**習慣化しない限りは、everyday no look life のはじまりです。**

理想は、**リマインド**。何か漏れているものがあれば、対応したい、それくらいの我儘があったりします。
Pushされるのではなく、**Pull型で決まった条件付きの情報を収集したい、というやつです。**

自分が調査したところ、**メンションされた投稿やメッセージを一覧化する**というアクションは見当たりません。

:::note warn
2024.05.28時点
:::

そこで、`Graph API`を使って、まずは**Outlookのメールだけでもなんとかできないか、挑戦してみます。**

# Graph API [mentionsPreview](https://learn.microsoft.com/ja-jp/graph/api/resources/mentionspreview?view=graph-rest-beta) リソース
今回の課題は、[mentionsPreview](https://learn.microsoft.com/ja-jp/graph/api/resources/mentionspreview?view=graph-rest-beta)を使って対処ができそうです。

また`beta`バージョンのAPIとのこと。

:::note warn
`/beta`バージョンのAPIであり、変更される可能性があります。 
:::

https://learn.microsoft.com/ja-jp/graph/api/resources/mentionspreview?view=graph-rest-beta

第1セグメント: `/me`、`/users/<userId>`、第2セグメント:`messages`、`mailFolders`、`events`、`calendar`、`calendars`、`outlook`、`inferenceClassification`の範囲内であることから、`Office 365 Outlook`コネクタで対応できそうです。

`Office 365 Outlook`コネクタの[HTTP 要求を送信する](https://learn.microsoft.com/ja-jp/connectors/office365/#http-%E8%A6%81%E6%B1%82%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B)アクションで、Graph APIを使ってみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b1872e8b-6e3c-257b-e5d9-525e3f135bed.png)

`Method` : `Get`

```plaintext:url
https://graph.microsoft.com/beta/me/messages?$filter=mentionsPreview/isMentioned+eq+true
```
これだけで、自分がメンションされたメールを一覧化することができます。

https://learn.microsoft.com/ja-jp/connectors/office365/#http-%E8%A6%81%E6%B1%82%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B

実際に使ってみると、`Outlook`の通知、下記の部分が取得できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/79b56172-98c0-deef-a563-2728e947653d.png)

`Office 365 Outlook`コネクタのアクションであるため、プレミアム コネクタなしで使えます。
個人情報も入っているので、戻り値は例で紹介します。

```json:body
{
  "@odata.context": "https://graph.microsoft.com/beta/$metadata#users('XXXXXX')/messages",  // ODataコンテキストURL
  "value": [
    {
      "@odata.etag": "W/\"CQAAABYAAADkSCYyPiA9RbDtjRLFGs9eAAHXd8D+\"",  // エンティティタグ
      "id": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Yy05MzM5LTJmZGQ3OWViZDcxNQBGAAAAAADfGay5QuF-RaPDhnhQhBiwBwDkSCYyPiA9RbDtjRLFGs9eAAAAAAEMAADkSCYyPiA9RbDtjRLFGs9eAAHYoEnHAAA=",  // メッセージID
      "createdDateTime": "2024-05-26T13:48:43Z",  // メッセージの作成日時
      "lastModifiedDateTime": "2024-05-26T15:29:40Z",  // メッセージの最終変更日時
      "changeKey": "CQAAABYAAADkSCYyPiA9RbDtjRLFGs9eAAHXd8D+",  // 変更キー
      "categories": [],  // メッセージのカテゴリ
      "receivedDateTime": "2024-05-26T13:48:43Z",  // メッセージの受信日時
      "sentDateTime": "2024-05-26T13:48:40Z",  // メッセージの送信日時
      "hasAttachments": false,  // 添付ファイルがあるかどうか
      "internetMessageId": "<OS3PR01MB9979FE7B27B56435AF10D47DA8F02@OS3PR01MB9979.jpnprd01.prod.outlook.com>",  // インターネットメッセージID
      "subject": "Re: 出戻り ガツオ さん",  // メールの件名
      "bodyPreview": "@出戻り ガツオ",  // メール本文のプレビュー
      "importance": "normal",  // メッセージの重要度
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Yy05MzM5LTJmZGQ3OWViZDcxNQAuAAAAAADfGay5QuF-RaPDhnhQhBiwAQDkSCYyPiA9RbDtjRLFGs9eAAAAAAEMAAA=",  // 親フォルダID
      "conversationId": "A------------------------------AAAA=",  // メールの会話ID
      "conversationIndex": "AQHaq3wohqJq/KBeUEupH6IVjmfdJLGrIiZr",  // メールの会話インデックス
      "isDeliveryReceiptRequested": false,  // 配信確認の要求
      "isReadReceiptRequested": false,  // 読了確認の要求
      "isRead": true,  // メッセージが既読かどうか
      "isDraft": false,  // メッセージがドラフトかどうか
      "webLink": "",  // メッセージをウェブで開くためのURL
      "inferenceClassification": "focused",  // メッセージの分類
      "unsubscribeData": [],  // 購読解除リンク
      "unsubscribeEnabled": false,  // 購読解除が有効かどうか
      "body": {
        "contentType": "html",  // メッセージ本文の形式
        "content": "htmlテキスト"  // メッセージ本文の内容
      },
      "sender": {
        "emailAddress": {
          "name": "大久保　絵梨",  // 送信者の名前
          "address": "okubo_eri@onmicrosoft.com"  // 送信者のメールアドレス
        }
      },
      "from": {
        "emailAddress": {
          "name": "大久保　絵梨",  // メッセージの送信元の名前
          "address": "okubo_eri@onmicrosoft.com"  // メッセージの送信元のメールアドレス
        }
      },
      "toRecipients": [
        {
          "emailAddress": {
            "name": "出戻り ガツオ",  // 宛先の名前
            "address": "hogehoge@onmicrosoft.com"  // 宛先のメールアドレス
          }
        }
      ],
      "ccRecipients": [],  // CCの受信者情報
      "bccRecipients": [],  // BCCの受信者情報
      "replyTo": [],  // 返信先アドレス情報
      "mentionsPreview": {
        "isMentioned": true  // メンションされているかどうか
      },
      "flag": {
        "flagStatus": "notFlagged"  // フラグの状態
      }
    }
  ]
}

```

メールの`id`、`html`を含めて、様々な値を取得することができます。
`isRead`や`Category`を使うことによって、抽出も可能。

[プロパティの詳細は下記を参考にしてください。](https://learn.microsoft.com/ja-jp/graph/api/resources/message?view=graph-rest-1.0#properties)

https://learn.microsoft.com/ja-jp/graph/api/resources/message?view=graph-rest-1.0#properties

##  抽出例：アーカイブされたメッセージ以外を対象にする
私の場合、**もう見ないメッセージは、Backspaceでアーカイブします。**
しかし、`アーカイブ`の場合、例文の中のプロパティでは判断できません。

`parentFolderId`は、`親フォルダID`であり、この手法で変更される値ではないためです。
発想を変えてみます。
メッセージを抽出する対象を`受信トレイ`に絞り、メンションされたメッセージを取得します。

このためには、
1. [メールボックスのIDを取得](https://qiita.com/DEmodoriGatsuO/items/57ecb042e4f8b553f630#1-%E3%83%A1%E3%83%BC%E3%83%AB%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%83%BCmailfolders%E3%81%AEid%E3%82%92%E5%8F%96%E5%BE%97)し
1. [メールボックスのIDを含めてGraph APIを実行](https://qiita.com/DEmodoriGatsuO/items/57ecb042e4f8b553f630#2-%E6%94%B9%E3%82%81%E3%81%A6%E3%83%A1%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%95%E3%82%8C%E3%81%9F%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92%E4%B8%80%E8%A6%A7%E5%8C%96)

上記の二段構えで対処します。

### 1. メールフォルダー(mailFolders)の`ID`を取得
こちらもGraph APIを使い、`メールフォルダー コレクション`を取得します。

https://learn.microsoft.com/ja-jp/graph/api/user-list-mailfolders?view=graph-rest-beta&tabs=http

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/43ba86a9-400e-b659-543e-dd234f37511d.png)

`Method` : `Get`

```plaintext:URI
https://graph.microsoft.com/v1.0/me/mailFolders
```

上記により、`メールフォルダー コレクション`を取得できます。

```json:戻り値
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('hogehogehogehogehoge')/mailFolders",
  "value": [
    {
      "id": "AAMkADBiYTQzZ----------------DtjRLFGs9eAAABb7e4AAA=",
      "displayName": "アーカイブ",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Yy05MzM5LTJm----------------AEIAAA=",
      "childFolderCount": 2,
      "unreadItemCount": 0,
      "totalItemCount": 31,
      "sizeInBytes": 6978775,
      "isHidden": false
    },
    {
      "id": "AAMkADBiYTQz----------------bDtjRLFGs9eAAAAAAEPAAA=",
      "displayName": "下書き",
      "parentFolderId": "AAMk----------------DtjRLFGs9eAAAAAAEIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 13432,
      "isHidden": false
    },
    {
      "id": "AAMkADBiYTQzZDYzLW----------------",
      "displayName": "会話の履歴",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtND----------------tjRLFGs9eAAAAAAEIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 0,
      "isHidden": false
    },
    {
      "id": "AAMkADBiY----------------=",
      "displayName": "削除済みアイテム",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI----------------jRLFGs9eAAAAAAEIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 1583000204,
      "isHidden": false
    },
    {
      "id": "----------------=",
      "displayName": "受信トレイ",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNvDtjRLFGs9eAAAAAAEIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 62280,
      "isHidden": false
    },
    {
      "id": "AAMkADBiYTQzZDYzLW----------------FGs9eAAAAAAELAAA=",
      "displayName": "送信トレイ",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Yy05MzM5----------------EIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 0,
      "isHidden": false
    },
    {
      "id": "AAMkADBiYTQzZ----------------bDtjRLFGs9eAAAAAAEJAAA=",
      "displayName": "送信済みアイテム",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Y----------------LFGs9eAAAAAAEIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 741258,
      "isHidden": false
    },
    {
      "id": "A----------------uF-RaPDhnhQhBiwAQDkSCYyPiA9RbDtjRLFGs9eAAFqodNcAAA=",
      "displayName": "同期の失敗",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Yy05MzM5LTJmZGQ3OWV----------------F-RaPDhnhQhBiwAQDkSCYyPiA9RbDtjRLFGs9eAAAAAAEIAAA=",
      "childFolderCount": 3,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 0,
      "isHidden": false
    },
    {
      "id": "AAMkADBiYTQzZDYzLWQ----------------fGay5QuF-RaPDhnhQhBiwAQDkSCYyPiA9RbDtjRLFGs9eAAAAAAEUAAA=",
      "displayName": "迷惑メール",
      "parentFolderId": "AAMkADBiYTQzZDYzLWQ4NzMtNDI4Yy05MzM5LTJmZGQ3OWViZDc-----------------RaPDhnhQhBiwAQDkSCYyPiA9RbDtjRLFGs9eAAAAAAEIAAA=",
      "childFolderCount": 0,
      "unreadItemCount": 0,
      "totalItemCount": 0,
      "sizeInBytes": 0,
      "isHidden": false
    }
  ]
}
```

単純な`JSON 配列入力`ですね。
`JSON の解析`アクションで、Schemaを定義しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/4674f1cc-ab52-5a2c-afcb-e382e087e8f0.png)

```plaintext:Content
@{body('HTTP_要求を送信します_mailFolders')}
```

```json:Schema mailFolders
{
    "type": "object",
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "value": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "displayName": {
                        "type": "string"
                    },
                    "parentFolderId": {
                        "type": "string"
                    },
                    "childFolderCount": {
                        "type": "integer"
                    },
                    "unreadItemCount": {
                        "type": "integer"
                    },
                    "totalItemCount": {
                        "type": "integer"
                    },
                    "sizeInBytes": {
                        "type": "integer"
                    },
                    "isHidden": {
                        "type": "boolean"
                    }
                },
                "required": [
                    "id",
                    "displayName",
                    "parentFolderId",
                    "childFolderCount",
                    "unreadItemCount",
                    "totalItemCount",
                    "sizeInBytes",
                    "isHidden"
                ]
            }
        }
    }
}
```

`アレイのフィルター処理`を使って、メンションされたメールを判別するフォルダーの設定、
つまり`受信トレイ`の`ID`を取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/94d4e041-0043-a208-dac3-5ccaf0d0c7a4.png)

`displayName`が`受信トレイ`のものがそのままマッチしますね。

### **2. 改めてメンションされたメールを一覧化**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/727755e7-0208-63b4-b9b6-8fc56a5f3a50.png)

`Method` : `Get`

```plaintext:URI
https://graph.microsoft.com/beta/me/mailFolders/@{body('アレイのフィルター処理')[0]?['id']}/messages?$filter=mentionsPreview/isMentioned+eq+true
```

`アレイのフィルター処理`の戻り値は配列であるため、`[0]`で抽出した値を特定します。
`mailFolders`の後に`ID`を追加することで、受信トレイのメールのみ取得できました。

さらに`アレイのフィルター処理`で、`receivedDateTime`を[getPastTime関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#getpasttime)で比較することで、直近1日以内のメッセージに絞ることができます。

```getPastTime関数
getPastTime(1, 'Day')
```

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#getpasttime

あとは`選択`で必要項目のみ抽出して、`HTMLテーブル`に変えて、`Teamsリマインド`など追加すれば、`リマインダー`が出来上がりますね。

※イメージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/150a482c-0528-eabc-0010-5bfaa106d236.png)

# 通知まみれ
それにしても通知まみれの環境になりました。
Always ピコピコブーブーです。

そんな状況にならないよう、環境整理からスタートすべきですかね。
お互い明日も頑張りましょう！