ささみ学習帳 - sasami's study book

ささみ学習帳

Microsoft365 や Power Platform について学んだこと・アイデアのメモ

Teams会議で録画を忘れているとおかんが教えてくれる Power Automate クラウドフロー

 

はじめに

私はTeams会議でうっかり録画を忘れてしまうことがよくあります。

そこで会議開始時刻を過ぎても録画をしていないとおかんが会議チャットで教えてくれるフローを作ってみました。

 

実行イメージ

会議の予定開始日時から2分経過しても録画をしていないと…

おかんが教えてくれます。

 

フロー全体図

 

フロー解説

フローの前半はこちらの記事で解説した内容そのままです。

予定表イベントから会議チャットのIdを取得しています。

sasami-axis.hatenablog.com

 

延期期限アクション以降の解説をします。

 

[Schedule]延期期限-会議開始時刻から2分経過まで待つ

会議が始まっているであろう時間まで待ちます。

今回はトリガーの出力に含まれているイベントの開始日時の2分後を設定しています。

  • Timestamp
    • addMinutes(
         triggerOutputs()?['body/start'],
         2,
          'yyyy-MM-ddTHH:mm:ssZ'
      )

 

 

[Control]スコープ-録画開始してるかチェック

 

[Microsoft Teams]Microsoft Graph HTTP 要求を送信する-会議チャットを取得

Graph APIで会議チャットに投稿されたメッセージを取得します。

 

learn.microsoft.com

 

Microsoft Graph HTTP 要求を送信するアクションを使うとこちらのエンドポイントでチャットのメッセージを取得することができます。

 

[Data Control]アレイのフィルター処理-録画開始メッセージをチェック

チャットメッセージの中に録画開始のメッセージが含まれていないかをチェックします。

  • From
    • @{body('Microsoft_Graph_HTTP_要求を送信する-会議チャットを取得')?['Value']}
  • Filter Query
    • @{item()?['eventDetail/callRecordingStatus']}
    • is equal to
    • initial

 

この部分は実際のチャットのメッセージリストで確かめました。

上記のAPIエンドポイントから返されるjsonではvalueのアレイの中に各メッセージが格納されています。

会議チャットの中で赤枠の部分のようなメッセージはシステムメッセージという扱いになるようです。システムメッセージに関しては、表示されているような文字はjsonには含まれません。

ですが、"eventDetail/callRecordingStatus" が録画の状態を表すようです。

この値は下記のように対応しているようです。

  •  "initial"
    • 録画開始
  • "chunkFinished"
    • 会議終了?
  • "success"
    • 録画完了

initialが含まれていない=録画が開始されていないと判定しています。

この為、録画開始後にすぐ停止してしまった場合にはこのフローのおかんは教えてくれません。

 

[Control]条件-録画してない?

アレイのフィルター処理の結果の数で分岐します。

 

  • 条件
    • @{length(body('アレイのフィルター処理-録画開始メッセージをチェック'))}
    • is equal to
    • 0

 

<Trueの場合>[Microsoft Teams]チャットやチャネルにカードを投稿する

会議チャットにアダプティブカードでおかんのメッセージを投稿します。

  • 投稿者
    • フローボット
  • 投稿先
    • Group chat
  • Group chat
    • @{outputs('作成-会議チャットid')}
  • Adaptive Card
    • Teams の開発者ツールアプリのアダプティブカードエディタで作成したものです。サンプルのカードをベースに最小限に削っただけのものです。画像もサンプルのままで実はおかんではありません。
    • {
          "type": "AdaptiveCard",
          "body": [
              {
                  "type": "TextBlock",
                  "size": "Medium",
                  "weight": "Bolder",
                  "text": "** 自動送信メッセージ **"
              },
              {
                  "type": "ColumnSet",
                  "columns": [
                      {
                          "type": "Column",
                          "items": [
                              {
                                  "type": "Image",
                                  "style": "Person",
                                  "url": "https://pbs.twimg.com/profile_images/3647943215/d7f12830b3c17a5a9e4afcc370e3a37e_400x400.jpeg",
                                  "size": "Small",
                                  "altText": "Example profile picture"
                              }
                          ],
                          "width": "auto"
                      },
                      {
                          "type": "Column",
                          "items": [
                              {
                                  "type": "TextBlock",
                                  "weight": "Bolder",
                                  "text": "おかん",
                                  "wrap": true
                              }
                          ],
                          "width": "stretch"
                      }
                  ]
              },
              {
                  "type": "TextBlock",
                  "wrap": true,
                  "size": "Large",
                  "text": "録画ボタン押した?\nお母さん、押し忘れてないか心配でね。あんたの大事な会議、録画されてなかったら大変やもんね。余計なことだったらごめんね、でもお母さんの心配性、許してや〜。"
              }
          ],
          "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
          "version": "1.4"
      }

 

考慮事項

おかんはあなたが参加するすべてのTeams会議に現れる

今回のフローでは、特に制限をしていないのでフロー実行アカウントが参加するすべての会議でおかんの心配性が発動します。

自分が主催・テナント内招待された会議までは動作する事を確認しています。チャネル会議や他テナントから招待された会議での動作は未確認です。

  • トリガー条件でおかんが心配する会議を制限する
    • @equals(triggerBody()?['organizer'],'自分のメールアドレス') ←自分の主催する会議のみ
  • イベントにカテゴリを付加し特定のイベントのみおかんに心配してもらう

といった制御は可能ですのでお好みでお試しください。

 

チャットをオフにした会議でもおかんは現れる

Teams会議のオプションでチャットをオフにできますが、おかんはそんなことお構いなしに突入してきます。おかんがメッセージを投稿するとチャットはオンに変わってしまいます。

 

Team会議urlの短縮で動作しなくなる可能性

Microsoft365のロードマップにて、今後Teams会議のURLが短縮される予定であることが発表されています。今回のフローは会議UrlからチャットIdを取得していますので、新しい会議Urlの仕様次第では動作しなくなるかもしれません。

www.microsoft.com

 

 

さいごに

Microsoft Teams コネクタにMicrosoft Graph HTTP 要求を送信するアクションが追加されたことで、プレミアムコネクタを使わずにできる事がとても増えました!

このフローのおかんは忘れている事を教えてくれることしかできません。

Teams会議のオプションで自動で録画を開始するオプションもありますが、会議に1人目が参加した時点で録画が開始されてしまうので使い勝手が良くない面もあります。

Microsoft へ製品のフィードバックを行えるフィードバックポータルにて、このようなアイデアが投稿されています。共感いただける方はぜひVoteを!

 

 

 

Power Automate クラウドフローから cohere の "Command R+" を使ってみた💎

 

はじめに

Command R+はCohere社が開発したLLMです。

特徴についてはあちこちで記事にされていますので省略しますが、

  • Web検索コネクタ(RAG)が標準提供されておりCopilot(Bing Chat)的にWebを基にした回答をAPIから生成できる
  • 無料プランでもAPIが使える
  • Coral(チャットUI)でPDFやテキストファイルを参照して回答できる(WebもOK)
  • ドキュメントが非常に充実している
  • Web UIがセンス良い

等が個人的に気に入っているポイントです。

今回はそんなCommand R+をPower Autoamteから利用してみました。

 

※プレミアムコネクタを利用します。Power Automate Premium等のライセンスが必要になります。

 

 

0.準備

公式でアカウント作成

Command R+はCohere公式だけでなくAzure、AWSでも利用可能です。今回は無料で試すことができるCohere公式を利用しています。

cohere.com

公式サイトにアクセスし「TRY NOW」をクリックし登録を行います。

登録完了するとダッシュボードが表示されます。

 

APIキーの取得

Web UIの使い方を書き始めると長くなりますので、さくっとAPIキーを取得します。

充実していますので一通り触ってみることをお勧めします。

 

ダッシュボードでAPI Keysをクリックします。

今回は個人的検証なので初めから生成されているTrial Keyを利用します。運用する場合は有償プランを契約しましょう。

👁️をクリックするとキーが表示されコピーアイコンも表示されるのでキーをコピーしておきます。

コピーしたAPIキーは安全な場所に保管しておきます。

 

 

1.シンプルに使ってみる

Power Automate クラウドフローからCommand R+を呼び出し回答を生成します。

トリガーのパラメータでプロンプトを入力し、プロンプトに対する回答を生成します。

 

フロー全体図

フロー解説

1.[Flow button for mobile]フローを手動でトリガーする

  • テキスト
    • prompt

 

2.[Data Control]作成-APIKey

APIキーを格納しています。本来はAzure Key Vaultなどを利用して安全に保管すべきですが、簡易的に作成アクション内に格納しています。

  • 入力
    • 「0.準備」で取得したAPIキー

 

3.[HTTP]HTTP-cohere api

APIを呼びます

  • URI
  • Method
    • POST
  • Headers
    • Authorization
      • Bearer @{outputs('作成-APIKey')}
    • Content-Type
  • Body
    • {
        "model": "command-r-plus",
        "message": "@{triggerBody()?['text']}"
      }
    • ※最小限のパラメータです。
    • リファレンスページに指定可能なパラメータが解説されています

 

フロー実行イメージ

こんなプロンプトで実行してみます。

応答はこのようなJSONで返されます。

cohere の APIの素敵な点として、chat_historyとして会話の履歴がすべて返されることです。この為チャットボットを作る場合には何も準備しなくても会話履歴を扱うことができます。

{
  "response_id": "305880b5-23dc-4e01-9beb-c053cc206183",
  "text": "日本で一番売れている和菓子の正確なランキングを特定することは困難ですが、人気の高い和菓子のひとつに「羊羹(ようかん)」があります。羊羹は、小豆あんをベースにした和菓子の定番で、さまざまな種類やブランドがあります。\n\n日本の市場調査会社であるインテージ株式会社の調査(2022年)によると、日本で最も売れている羊羹のブランドは「本町駿河屋」の「特選 煉羊羹」です。この羊羹は、伝統的な製法で作られ、しっとりとした食感と上品な甘みが特徴です。\n\n他にも、以下のような人気の和菓子が挙げられます。\n\n- 大福:柔らかい餅で餡子を包んだ和菓子。さまざまなフレーバーの大福があり、特にイチゴ大福やクリーム大福が人気です。\n- 饅頭(まんじゅう):小麦粉や米粉の生地で餡子を包んで蒸したり焼いたりした和菓子。地域によってさまざまな種類があります。\n- 団子(だんご):餅粉で作った小さな球状の和菓子。串に刺して食べることが多いです。みたらし団子やあんこ団子が人気です。\n- 煎餅(せんべい):米を原料に焼き上げた薄い焼き菓子。さまざまな味付けやトッピングがあります。\n\nこれらの和菓子は、日本全国で広く愛されており、お土産や贈答品としても人気があります。",
  "generation_id": "8773f562-ad61-4428-9066-28e7d73025b0",
  "chat_history": [
    {
      "role": "USER",
      "message": "日本で一番売れている和菓子は?"
    },
    {
      "role": "CHATBOT",
      "message": "日本で一番売れている和菓子の正確なランキングを特定することは困難ですが、人気の高い和菓子のひとつに「羊羹(ようかん)」があります。羊羹は、小豆あんをベースにした和菓子の定番で、さまざまな種類やブランドがあります。\n\n日本の市場調査会社であるインテージ株式会社の調査(2022年)によると、日本で最も売れている羊羹のブランドは「本町駿河屋」の「特選 煉羊羹」です。この羊羹は、伝統的な製法で作られ、しっとりとした食感と上品な甘みが特徴です。\n\n他にも、以下のような人気の和菓子が挙げられます。\n\n- 大福:柔らかい餅で餡子を包んだ和菓子。さまざまなフレーバーの大福があり、特にイチゴ大福やクリーム大福が人気です。\n- 饅頭(まんじゅう):小麦粉や米粉の生地で餡子を包んで蒸したり焼いたりした和菓子。地域によってさまざまな種類があります。\n- 団子(だんご):餅粉で作った小さな球状の和菓子。串に刺して食べることが多いです。みたらし団子やあんこ団子が人気です。\n- 煎餅(せんべい):米を原料に焼き上げた薄い焼き菓子。さまざまな味付けやトッピングがあります。\n\nこれらの和菓子は、日本全国で広く愛されており、お土産や贈答品としても人気があります。"
    }
  ],
  "finish_reason": "COMPLETE",
  "meta": {
    "api_version": {
      "version": "1"
    },
    "billed_units": {
      "input_tokens": 8,
      "output_tokens": 334
    },
    "tokens": {
      "input_tokens": 74,
      "output_tokens": 334
    }
  }
}

 

2.Webを検索して回答を生成する

続いてマネージドなWeb検索コネクタをつかってみます。

入力したキーワードをWeb検索して、結果を箇条書きにまとめて返してくれるフローです。

フロー全体図

フロー解説

1.[Flow button for mobile]フローを手動でトリガーする

  • テキスト
    • prompt

 

2.[Data Control]作成-APIKey

APIキーを格納しています。本来はAzure Key Vaultなどを利用して安全に保管すべきですが、簡易的に作成アクション内に格納しています。

  • 入力
    • 「0.準備」で取得したAPIキー

 

3.[HTTP]HTTP-cohere api

APIを呼びます

  • URI
  • Method
    • POST
  • Headers
    • Authorization
      • Bearer @{outputs('作成-APIKey')}
    • Content-Type
  • Body
    •   "model": "command-r-plus",
        "message": "@{triggerBody()?['text']}",
        "connectors": [
          {
            "id": "web-search"
          }
        ]
      }
    • 1つめのjsonに  connectors=[{"id": "web-search"}]を追加しただけです。
      • web-search がWeb検索コネクタを指定しています
      • コネクタを作成して追加することができるようです
    • ※最小限のパラメータです。
    • リファレンスページに指定可能なパラメータが解説されています

 

フロー実行イメージ

LLMは学習していないであろうこんなプロンプトで実行してみます。

このような回答がされました(正解)

 

APIの応答はこのようなJSONで返されます。

6つのWebページの情報を基に回答を生成していることがわかります。

(長いのでスクリーンショット)

 

ちなみに、Webコネクタ未使用の場合は間違った日付が返されました。

LLMが回答を持っている訳ではなく、Webの情報から回答を生成していることが確認できました。

 

3.指定ドメインをWeb検索して回答を生成する

2.はWeb全体から検索する形でしたが、指定したドメイン内のページから回答を生成することも可能です。

フローは2と全く同じです。Bodyに指定するjsonに ,"options": {"site": "<検索するサイトのドメイン>"} を加えることで検索対象を指定することができます。

{
  "model": "command-r-plus",
  "message": "@{triggerBody()?['text']}",
  "connectors": [
    {
      "id": "web-search",
      "options": {
        "site": "ja.wikipedia.org"
      }
    }
  ]
}

 

解決できなかったこと

JSON出力させるとMarkdown的な出力に…

cohere APIには出力形式をjsonに指定するようなオプションは提供されていないようです。そこでプロンプトでjsonで返すよう指示をするとこのようにMarkdownのコードブロックとして出力してしまいます。プロンプトでこれを抑制しようと試行錯誤したのですが解決できませんでした。必ずMarkdown的にに出力される前提で出力結果を加工してしまえば対処は可能ですが、できればプレーンなjsonとして出力させたいところでした。

 

 

参考にしたページ

docs.cohere.com

 


さいごに

やっぱり公式ドキュメントが充実しているサービスは使いやすい!

Power Automate クラウドフローからcohere API経由で Command R+を使ってみました。ごくごく基本的な使い方のみですが、Power Automate や Power Apps から CopilotのようにWebを基にした回答を生成できるのは、いろいろな使い方が思いついて夢が膨らみます。

 

 

 

 

Power Automate クラウドフローで Bing Custom Search APIを利用してWeb検索を行う 💎

 

はじめに

先日こちらの投稿ではBing Werb Search APIを使ってWebページを検索してみました。

sasami-axis.hatenablog.com

今回は、Bing Custom Search APIを使って任意のサイト内検索をPower Automate クラウドフローから行ってみました。

 

※HTTPコネクタを利用する為Power Automate Premiumライセンスなどが必要になります。

 

Bing Custom Search APIとは

Microsoft検索エンジン Bingを使って、特定のサイトや一連のWebサイトからコンテンツを検索することができるAPIです。今回はPower Automate から利用していますが、今話題のCopilot StudioもBing Custom Searchに対応しています。

 

【重要】Bing Search API の要件を確認しておきましょう

こちらのページにBing Search APIの要件があります。禁止事項などがありますので必ず確認しておきましょう。

learn.microsoft.com

 

また、Power AutomateでBing の検索結果を取得したら生成AIに渡してあれこれしたくなってきますが、こちらのページでLLMとBingSearch APIを組わせて使う場合の要件が説明されています。そういった用途の場合は必ずこちらのページを確認しましょう。

learn.microsoft.com

 

Bing Search API は従量課金制です

詳しい価格はこちらのページで確認できます。

今回は無料枠で利用しています。

www.microsoft.com

 

 

準備作業1-Azure PortalでBing Custom Serach リソースを作成する

※Azureアカウント、サブスクリプション、リソースグループはあらかじめ作成済みの状態から説明しています。

 

1.こちらのURLからBing カスタム検索 リソースの作成ページを開けます

https://portal.azure.com/#create/microsoft.bingcustomsearch

 

2.Azure PortalにサインインしBing カスタム検索 リソースを作成する

 

  • サブスクリプション
    • あらかじめ作成しておく必要があります
  • リソースグループ
    • 複数のリソースをまとめて管理するためのグループです。作成済みのリソースグループがある場合は選択し、ない場合はこのページから新規作成もできます。
  • 名前
    • Bing カスタム検索 リソースの名前を付けます
  • リージョン
    • グローバルのまま変更不要
  • 価格レベル

全て設定したら契約条件に同意するチェックをオンにし「確認と作成」をクリックします。

 

3.選択した内容を確認し問題なければ「作成」をクリックするとリソースが作成され舞す

4.作成が完了したらリソースに移動します

5.作成したBing カスタム検索 リソースを開くとこんな画面が表示されます

ページ中央「お試しください」の下で実際に検索を試すことができますが、試すには準備作業2でカスタム設定を作成する必要があります。

 

6.画面中央右のキーの管理の「click here to manage keys 」をクリックします

 

7.Key1の右端のアイコンをクリックしAPIキーをクリップボードにコピーします

コピーしたキーは安全な場所に保管しておきます。

 

以上で、Azure Portalでの準備作業は完了です。

 

準備作業2-Bing Custom Search のカスタム設定を作成する

Bing Custom Search の検索条件を指定するカスタム設定を作成していきます。

 

1.Bing Custom Search にアクセス

https://www.customsearch.ai/

 

2.「Get Started」ボタンをクリック

Microsoftのサインインページに移動しますので、

個人向けのMicrosoftアカウント・法人向けの組織または学校アカウントどちらかでサインインします。

3.利用条件を確認し同意できる場合はチェックし「Agree」をクリック

 

4.Welcomeな表示を確認して閉じます

ここからは表示の順に進めていきます。

 

5.「Create New Instance」をクリック

 

6.インスタンス(=カスタム設定)の作成

作成するカスタム検索のインスタンス名(カスタム設定の名称)を設定します。今回は道の駅の情報を検索する設定を作ってみますので「MichinoEKi」という名前を入力しOKをクリックします。

作成が完了すると、インスタンスの設定画面が表示されます。

 

6-1.検索対象のサイトを設定

表示されたページで検索対象のページを設定します。

今回は下記2つのサイトを設定します。

 

ActiveタブにURLを追加していきます。1つ目はまず中央の赤枠に入力し「Include Subpages」はチェックを入れたままにして+をクリックすると追加されます。

 

「Type in a URL」のところに入力して2つ目以降を追加します。

 

右側の検索プレビューで実際に検索してみることができます。

動作を確認して問題ない場合は「Publish」をクリックしてインスタンスを公開します。

成功したら「Go to production environment」をクリックします

運用環境のページが表示されたら「Custom Configuration ID」の値をコピーして安全な場所に保存しておきます。

 

このページでも実際に検索を試すことができます。

Azure Portalで作成したBing Custom Search リソースのキーを「Subscription Key」に入力する必要があります。

 

 

フロー全体図

 

フロー解説

1.[Flow button for mobile]フローを手動でトリガーする

テストフローなのでこちらをトリガーにしています。

  • パラメータ1:検索キーワード
    • テキスト

 

2.[Data Control]作成-BCS-SubscriptionKey

本来は Azure Key Valutを使って安全な状態でキーを管理すべきですが、作成環境の都合で今回は作成アクションにキーを格納しています。

 

3.[HTTP]HTTP-Bing Web Search API

Bing Custom Search APIを呼びます。



  • URI
  • Method
    • GET
  • Headers
    • Ocp-Apim-Subscription-Key
      • @{outputs('作成-API_Key')}

 

「道の駅豊橋」を検索キーワードに入力して実行してみました。

するとこんな感じのjsonで返されます。

こちらのページに応答jsonオブジェクトの説明があります。

learn.microsoft.com

 

参考にしたページ

learn.microsoft.com

 

learn.microsoft.com

 

さいごに

使い方は先日投稿したBing Web Search APIとほとんど変わりません。カスタム設定をあらかじめ作成しておくことくらいです。Bing Custom Search を利用すると、指定した単一のサイトだけでなく複数のWebページ、サイトだけから検索することができますので、Power Automate クラウドフローからはこちらの方が利用できるシーンは多いかもしれません。

Power Automate クラウドフローで Bing Web検索を行う 💎

 

はじめに

Microsoft検索エンジン Bing にはプログラムから検索を行うことができるAPIが用意されています。今回は、Power Automate クラウドフローからAPIを使ったBing検索を試してみました。

 

※HTTPコネクタを利用する為Power AUtomate Premiumライセンスなどが必要になります。

 

Bing Search コネクタはWeb検索には対応していない

Power Automate では Bing Searchコネクタを利用することができますが、残念ながらニュースを検索するアクションしかありません(2024年5月時点)。まだプレビューとなっているコネクタですので今後の機能強化に期待しましょう。

※Bing Search コネクタはPremiumコネクタではありませんが、利用するためにはAzure PortalでBing Searchリソースを作成する必要があります。

 

 

Bing Search APIとは

Microsoft検索エンジン Bingの検索をプログラムから行うことができるインターフェースです。

  • Web Search API
  • Image Search API
  • News Search API
  • Video Search API
  • Visual Search API
  • Custom Search API
  • Entity Search API
  • Spell Check API
  • Autosuggest API

等多数のAPIが含まれておりWebページだけでなく画像やビデオ、ニュースなどを取得するAPIも提供されています。

これらのうち、今回はWeb Search APIを利用します。

 

【重要】Bing Search API の要件を確認しておきましょう

こちらのページにBing Search APIの要件があります。禁止事項などがありますので必ず確認しておきましょう。

learn.microsoft.com

 

また、Power AutomateでBing の検索結果を取得したら生成AIに渡してあれこれしたくなってきますが、こちらのページでLLMとBingSearch APIを組わせて使う場合の要件が説明されています。そういった用途の場合は必ずこちらのページを確認しましょう。

learn.microsoft.com

 

準備作業-Azure PortalでBing Serach リソースを作成する

※Azureアカウント、サブスクリプション、リソースグループはあらかじめ作成済みの状態から説明しています。

 

1.Bing Search API のページを開き、「Try Now」をクリック

https://www.microsoft.com/en-us/bing/apis

2.Azure PortalにサインインしBing Search リソースを作成する

  • サブスクリプション
    • あらかじめ作成しておく必要があります
  • リソースグループ
    • 複数のリソースをまとめて管理するためのグループです。作成済みのリソースグループがある場合は選択し、ない場合はこのページから新規作成もできます。
  • 名前
    • Bing Search リソースの名前を付けます
  • リージョン
    • グローバルのまま変更不要
  • 価格レベル

全て設定したら契約条件に同意するチェックをオンにし「確認と作成」をクリックします。

 

3.選択した内容を確認し問題なければ「作成」をクリックするとリソースが作成され舞す

4.作成が完了したらリソースに移動します

5.作成したBing Searchリソースを開くとこんな画面が表示されます

ページ中央「お試しください」の下で実際に検索を試すことができます。

6.画面中央右のキーの管理の「click here to manage keys 」をクリックします

 

7.Key1の右端のアイコンをクリックしAPIキーをクリップボードにコピーします

コピーしたキーは安全な場所に保管しておきます。

 

以上で、Azure Portalでの準備作業は完了です。

 

フロー全体図

 

フロー解説

1.[Flow button for mobile]フローを手動でトリガーする

テストフローなのでこちらをトリガーにしています。

 

2.[Data Control]作成-API Key

本来は Azure Key Valutを使って安全な状態でキーを管理すべきですが、作成環境の都合で今回は作成アクションにキーを格納しています。

  • 入力
    • Bing Serach APIのキー

 

3.[HTTP]HTTP-Bing Web Search API

Bing Web Search APIを呼びます。

 

こんな感じのjsonで返されます。

 

こちらのページに応答jsonオブジェクトの説明があります。WebPagesに関するところはこちらです。

learn.microsoft.com

 

 

参考にしたページ

www.microsoftするom

 

learn.microsoft.com

 

気になった点

site: オプションは機能しない?

Bingで検索する時例えば「apple キーボード site:yodobashi.com」とsite:を使ってドメインを指定する事が出来ます。

リファレンスページにはこのように検索オプションが使用できることが明記されています。しかし、試した限り site: (検索結果をドメイン指定でフィルターリングするオプション)を指定してもWebページと同様に指定すると結果を返さなくなり、リファレンスページように+でキーワードを結合しても異なるドメインが含まれることがあり意図した結果になりませんでした。この辺りコツがいるのかもしれません。

今回はあまり深く追求していません。特定ドメインを検索するのであれば「Bing Custom Search API」がありますのでそちらを使う事にしました。

「Bing Custom Search API」に続きます。

 

Outlook on the Web でメールをダイレクトに開くURLを取得する

 

はじめに

Graph API でメールを取得するとメールにwebLinkというプロパティがあり、このリンクにアクセスするとOutlook on the Webでメールを直接開くことができます。

このURLがあればメールと他のアプリの連携がやりやすくなり便利そうなのですが、このURLを取得する方法はOutlook on the Webのメールの画面を探しても見つかりませんでした。そこでGraph APIを使わずにメールのURLを取得する方法を調べてみました。

learn.microsoft.com

 

URLを取得する方法

1.Outlook on the Web でメールにフラグを付ける

 

2.Microsoft To Doを開く

 

3.To Do で「フラグを設定したメール」リストを開く

 

4.メールのタスクをクリック

 

5.「開く」を右クリックしてリンクのコピー

 

以上の手順でメールへのリンクが取得できます。

 

 

URLの形式について

Graph APIとTo Doのタスクから取得できるメールのURLは同じ形式で、次のような形になっています。

 

https://outlook.office365.com/owa/
?ItemID={id}
&exvsurl=1
&viewmodel=ReadMessageItem

{id}にはメールの内部的なidが指定されています。

その他のパラメーターの意味は分かりませんでした。

 

このURLにアクセスすると、下記の形式のURLにリダイレクトされます。

https://outlook.office365.com/mail/deeplink/read/{id}%3d
?ItemID={id}
&exvsurl=1

※?以降のパラメータを削除しても開くことができました。

 

 

learn.microsoft.com

 

Power Automate クラウドフローで楽をする(1)

少数であればTo Do からリンクを取得するもありですが、数が増えると面倒になってきます。

例えば、こんな簡単なフローを作っておくと、フラグを付けたメールのリンクをTeamsチャットに投稿します。

Power Automate クラウドフローで楽をする(2)

To Do のフラグ付きメールのリストをCSV出力するフローです。リンクが欲しいメールにフラグを付けておき、このフローを実行してCSVファイルに一括出力させる方法です。

フロー解説

1.[Flow button for mobile]フローを手動でトリガーする

 

2.[Microsoft To-Do (Business)]フォルダー別に To Do を一覧表示する (V2)

  • To Do リスト
    • Flagged Emails

 

3.[Data Control] 選択

  • From
    • @{body('フォルダー別に_To_Do_を一覧表示する_(V2)')}
  • Maps
    • title
      • @{item()?['title']}
    • createDateTime
      • @{item()?['createdDateTime']}
    • WebUrl
      • @{item()?['linkedResources'][0]?['webUrl']}

 

4.[Data Control]CSVテーブルの作成

  • From
    • @{body('選択')}

 

5.[OneDrive for Business]ファイルの作成

  • フォルダーのパス
    • /MailExport/
  • ファイル名
    • mailexport-@{convertFromUtc(utcNow(), 'Tokyo Standard Time', 'yyyy-MM-ddTHHmmss')}.csv.txt
    • 文字コードがutf8のCSVファイルとして作成されるため、Excelで文字化けせず開きやすいようあえて.txtとしています
  • ファイルコンテンツ
    • @{body('CSV_テーブルの作成')}

 

関連ページ

sasami-axis.hatenablog.com

 

さいごに

今回の手段は自分のメールボックスだけで使えます。共有メールボックスやMicrosoft365グループのメールボックスのメールの場合は、フラグを付ける機能がなかったり、To Doにタスクを追加することができませんでした。解決策を思いついたらまた記事にします。

 

Outlookの指定したメールスレッドで返信が一定期間滞ったら、To Doに返信を催促するタスクを追加するPower Automate クラウドフロー

 

はじめに

メールは非同期コミュニケーションです。即時反応を求めるものではありません。とはいえ、ビジネスメールではある程度の期間内には返信が期待されることもあります。

返信が遅いことが予想される相手あてのメールについて、一定期間経過しても返信がなかった場合に、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 を呼び出しています。

この辺りは過去にこちらの記事にまとめています

sasami-axis.hatenablog.com

 

 

 

4-2.[Data Control]選択-conversationId

分類付きメールのアレイから、メールのスレッドを識別するid(conversationId)のみを抽出します。

  • From
    • @{body('HTTP_要求を送信します-要注意分類のメッセージを検索')?['value']}
  • Map
    • conversationId
      • @{item()?['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 のメッセージを取得するエンドポイントを利用します。

learn.microsoft.com

 

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を取得します。この辺りの解説はこちらの記事にまとめています。

sasami-axis.hatenablog.com

 

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につくらせるというのも面白そうです。

 

 

Microsoft To-Do (Business)コネクタを使ったPower Automateクラウドフローを他のアカウントにインポートするとそのままでは動作しないことへの対処を考える

 

はじめに

Microsoft To-Do (Business)コネクタを使ったフローを他のアカウントにインポートして実行する場合という限定された条件での気づきです。

 

Microsoft To-Do (Business)コネクタを使ったフローを他のアカウントにインポートするとそのままでは動作しない

例えばMicrosoft To-Do (Business)コネクタの「フォルダー別にTo Doを一覧表示する(V2)」アクションで、デフォルトのタスクリストに登録されているタスクを取得しているフローを作ったとします。

 

フローを作成したアカウントで実行するだけであれば問題ありませんが、このフローを他のアカウントにインポートして使うと、実行するとエラーになります。

「item not found」エラーです。これはリストが見つからない状態です。エクスポートしたアカウントにも「タスク」リストはもちろん存在します。

 

どうして…?

では、アクションをコードビューで見てみましょう。

To Do リストは内部的にはfolderIdという形でidで識別されていることがわかります。

インポートしたフローに同じアクションを追加して「タスク」リストを選択しコードビューで確認すると、インポートしたままのアクションとは内部的なidが異なっていることがわかります。

Microsoft To Doのデフォルト「タスク」は各アカウントに存在します。しかし内部的には異なるidで管理されているため、フローをインポートしただけではidが異なるためエラーとなってしまうわけです。

 

対策を考える

[対策1]フローをインポートした後で使用しているTo Doコネクタのアクションでリストを選択しなおす

シンプルです。ただ、多数のアクションを使用しているフローではそれなりの手間となったり、修正漏れの可能性が出てきます。

 

[対策2]デフォルトの「タスク」リストを動的に取得するフローにしておく

考え方

アクションでリストを指定するのではなく、あらかじめタスクリストのidを取得して、アクションのパラメータでタスクリストを指定するところにカスタム値で設定することで、他のアカウントでもそのまま動作させられるようになります。

フロー解説

1.すべての To do リストを一覧表示する(V2)

まずすべてのリストを取得します。

 

2.[Data Operation]アレイのフィルター処理

デフォルトのタスクリストをフィルターします。

  • From
    • @{body('すべての_To_do_リストを一覧表示する_(V2)')}
  • Filter Query
    • @{item()?['Name']}
    • is equal to
    • タスク

 

※デフォルトのタスクリストは既知の名前(wellknownListName)を使用してフィルタすることもおすすめです。

この既知の名前(wellknownListName)は、デフォルトで存在するタスク(defaultList)・フラグを設定するメール(flaggedEmails)の2つのリストに設定されているようです。

デフォルトのタスクリストは、メールボックスの設定次第で異なる言語の名前になっている場合があります。そのような可能性があるテナントでは既知の名前(wellknownListName)でフィルターすれば、メールボックスの設定に依存せずフィルターすることができます。

 

3.[Microsoft To Do (Business] フォルダー別にTo Doを一覧表示する

  • To Do リスト
    • カスタム値で式として設定
    • body('アレイのフィルター処理-タスク')[0]?['id']