PowerAutomateワークフローからTeamsのチャネルにメッセージを通知

はじめに

この記事ではAzure MonitorのアラートをMicrosoft Teamsに通知する方法を紹介します。

PowerAutomateワークフローを作成する

ワークフローを作成する場合、 PowerAutomateのWEBサイトか、 TeamsのWEBサイトまたはアプリから作成が可能です。 この記事では、 Teamsアプリからワークフローの作成を行います。

PowerAutomate

以下の手順で作成を行います。

  1. 通知対象のチャネルのメニューからワークフローを選択する

  1. Webhook要求を受信するとチャネルに投稿する

  1. ワークフローの名前を入力し、ワークフローを追加

  1. 追加後に表示されるワークフローのURLを控える

Adaptive Cardでの通知

ワークフローから通知を行う際は、 メッセージの形式をAdaptive Cardにする必要があります。
Adaptive Cardは、 JSONで記述されたUI要素を、 アプリケーションで表示する際のJSONの標準フォーマットです。
Adaptive Cardは、 Teams、 Outlook、 Androidアプリ、 iOSアプリなどのマルチプラットフォームに対応(Adaptive)しています。

以下のサイトで、 Adaptive Cardのプレビューが可能です。

Designer | Adaptive Cards

Adaptive Cardで通知を行うPythonコード

ワークフローの作成完了後は、 ワークフローのURLに通知を送信するPythonコードを用意します。

  • .env
TEAMS_WEBHOOK_URL=コピーしたワークフローのURLを設定
  • main.py 以下のコードはテキスト、 テーブル、 ファクトセットの3 種類メッセージをポストする。
import os
import requests
from dotenv import load_dotenv
load_dotenv()

# URL取得
WEBHOOK_URL = os.getenv("TEAMS_WEBHOOK_URL")

# リクエストヘッダー
headers = {
    "Content-Type": "application/json"
}

# テキスト形式 --------------------------------------------------------------------------------
text_request_body = {
    "type": "message",
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.adaptive",
            "contentUrl": None,
            "content": {
                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                "type": "AdaptiveCard",
                "version": "1.4",
                "body": [
                    {
                        "type": "TextBlock",
                        "text": "TextBlock: 単純なテキストを表示するための要素",
                        "weight": "Bolder",
                        "size": "Medium"
                    },
                    {
                        "type": "TextBlock",
                        "text": "[TextBlock:リンクの設定する場合は`[リンク名](URL)`]( https://qiita.com/fukasawah/items/896c3638c203a973c2f0 )"
                    },
                    {
                        "type": "Image",
                        "url": "https://adaptivecards.io/content/adaptive-card-50.png",
                        "altText": "Image: 画像を表示するための要素"
                    },
                    {
                        "type": "RichTextBlock",
                        "inlines": [
                            {
                                "type": "TextRun",
                                "text": "RichTextBlock: 複数のテキストスタイルや書式を含む複雑なテキストを表示するための要素",
                                "color": "Accent"
                            },
                            {
                                "type": "TextRun",
                                "text": " (TextRun: RichTextBlock内で使用される、個別のテキスト要素)",
                                "italic": True
                            }
                        ]
                    }
                ]
            }
        }
    ]
}
try:
    # リクエスト送信
    response = requests.post(WEBHOOK_URL, headers=headers, json=text_request_body)
    # レスポンスの確認
    print(f"data: {text_request_body}")
    print(f"Status Code: {response.status_code}")
    print(f"Response Text: {response.text}")
except Exception as e:
    print(f"Error: {e}")

# テーブル形式での表示 --------------------------------------------------------------------------------
table_request_body = {
    "type": "message",
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.adaptive",
            "contentUrl": None,
            "content": {
                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                "type": "AdaptiveCard",
                "version": "1.4",
                "body": [
                    {
                        "type": "Table",
                        "gridStyle": "accent",
                        "firstRowAsHeaders": True,
                        "columns": [
                            {
                                "width": 1
                            },
                            {
                                "width": 1
                            },
                            {
                                "width": 1
                            }
                        ],
                        "rows": [
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Header1",
                                                "wrap": True,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Header2",
                                                "wrap": True,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Header3",
                                                "wrap": True,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    }
                                ],
                            },
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Value1",
                                                "wrap": True
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Value2",
                                                "wrap": True
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Value3",
                                                "wrap": True
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        }
    ]
}
try:
    # リクエスト送信
    response = requests.post(WEBHOOK_URL, headers=headers, json=table_request_body)
    # レスポンスの確認
    print(f"data: {table_request_body}")
    print(f"Status Code: {response.status_code}")
    print(f"Response Text: {response.text}")
except Exception as e:
    print(f"Error: {e}")

注意事項

リクエストボディに指定するスキーマバージョンは 1.4 以下に設定する必要がある

最新バージョンは1.6だが、 ワークフローからTeamsに送信する場合、 1.4以下にしないと We’re sorry, this card couldn’t be displayed と表示され、 Teams上でメッセージの表示ができないため、バージョンは1.4に固定する必要があります。

Adaptive Card Designer を使って Teams用カードを作ろう - Qiita

"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",

プライベートチャネルには通知ができない

Private チャネルにワークフローを作成しようとすると、 「ワークフローのインストールができない」 と表示されるので、 テキスト用の通知先を作成する場合は、 一時的にパブリックチャネルに通知用のチャネルを作成する必要があります。


おわりに

この記事ではPowerAutomateを使って、Microsoft Teamsに通知する方法を紹介しました。
この記事がエンジニアの方の参考になれば幸いです。