はじめに
Teams エクスポート Graph API を利用すると、Teams のメッセージを簡単な処理でエクスポートすることができます。Teams エクスポート API について検証した内容をまとめてみました。
Teams エクスポート API
Teams のメッセージを取得する Graph API として、メッセージ一覧取得 API があります。Teams エクスポート API とメッセージ一覧取得 API には以下のような違いがあります。
(参考:Microsoft Teamsエクスポート API を使用してコンテンツをエクスポートする)
https://learn.microsoft.com/ja-jp/microsoftteams/export-teams-content
(参考:シナリオに適した API の選択)
https://learn.microsoft.com/ja-jp/graph/teams-messaging-overview#choosing-the-right-api-for-your-scenario
メッセージ一覧取得 API との違い
名前 | 取得対象 | アクセス権限 | $top で一度に取得できる件数 | 課金 |
---|---|---|---|---|
エクスポート API | 特定の チーム またはグループチャット内のメッセージ | アプリケーション許可権限のみ | 1,000~(※) | あり |
メッセージ一覧取得 API | 特定の チャネル またはグループチャット内のメッセージ | ユーザー委任権限、またはアプリケーション許可権限 | 50 | なし |
エクスポート API を利用するにはライセンスや従量課金のため Azure サブスクリプションが必要になります。ライセンス要件については後述しています。
エクスポート API ではメッセージの返信も含めて取得することができます。
メッセージ一覧取得 API では、メッセージの返信を取得することはできず、返信を取得する API によって別途取得する必要があります。
※ エクスポート API では $top = 250 を指定してページングによってメッセージを取得すると効率よく処理することができます (詳しくはこちら)。
(参考:応答を一覧表示する)
https://learn.microsoft.com/ja-jp/graph/api/chatmessage-list-replies?view=graph-rest-1.0&tabs=http
URI の比較
チーム内のメッセージ
- エクスポート API
/teams/{team-id}/channels/getAllMessages - メッセージ一覧取得 API
/teams/{team-id}/channels/{channel-id}/messages
エクスポート API はチーム ID を指定するだけで、チーム内のすべてのチャネルのメッセージを取得することができます。
メッセージ一覧取得 API はチャネル ID の指定が必要です。
(参考:channel: getAllMessages)
https://learn.microsoft.com/ja-jp/graph/api/channel-getallmessages?view=graph-rest-1.0&tabs=http
(参考:チャネル メッセージを一覧表示する)
https://learn.microsoft.com/ja-jp/graph/api/channel-list-messages?view=graph-rest-1.0&tabs=http
グループチャットのメッセージ
- エクスポート API
/users/{user-id}/chats/getAllMessages - メッセージ一覧取得 API
/chats/{chat-id}/messages
エクスポート API はユーザー ID を指定するだけで、ユーザーが参加しているすべてのグループチャットのメッセージを取得することができます。
メッセージ一覧取得 API はチャット ID の指定が必要です。
(参考:チャット: getAllMessages)
https://learn.microsoft.com/ja-jp/graph/api/chats-getallmessages?view=graph-rest-1.0&tabs=http
(参考:チャット内のメッセージを一覧表示する)
https://learn.microsoft.com/ja-jp/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http
ライセンス要件
エクスポート API は用途によってライセンス要件が異なります。
用途 | 支払いモデル | DLP ライセンス | 課金 | 備考 |
---|---|---|---|---|
セキュリティやコンプライアンス | A | 必要 | あり | アプリごとに毎月ライセンス数 x 800 メッセージまで無料 |
バックアップ | B | 不要 | あり | 無料枠なし |
評価 | - | 不要 | なし | アプリごとに毎月 500 メッセージまで |
エクスポート API を実行する際に、URI の "model" パラメータによって支払いモデルを指定します。指定しない場合は評価モードになります。
- 支払いモデル A で実行する
/teams/{team-id}/channels/getAllMessages?model=A - 支払いモデル B で実行する
/teams/{team-id}/channels/getAllMessages?model=B - 評価モードで実行する
/teams/{team-id}/channels/getAllMessages
従量課金でエクスポート API を実行するためには Azure サブスクリプションを使用して、従量課金を有効化する必要があります。この記事の最後で手順を紹介しています。
支払いモデル A の場合に必要なライセンス
支払いモデル A の場合には "Microsoft Communication DLP" が含まれるライセンスが必要になります。Microsoft 365 E5 などのライセンスに含まれています。
"Microsoft Communication DLP" は Microsoft 365 E5 Developer ライセンスにも含まれています。
(参考:Microsoft Teams API の支払いモデルとライセンス要件)
https://learn.microsoft.com/ja-jp/graph/teams-licenses
(参考:Teams データ損失防止 (DLP) および Teams エクスポート向け Microsoft Purview データ損失防止 Graph API)
https://learn.microsoft.com/ja-jp/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-purview-service-description#microsoft-purview-data-loss-prevention-graph-apis-for-teams-data-loss-prevention-dlp-and-for-teams-export
利用方法
エクスポート API の検証
Graph PowerShell でテスト用のチームに 1,000 件のメッセージを投稿して、エクスポート API によって取得してみます。
事前準備
以下のように特定のチャネルに 1,000 件メッセージを投稿します。チャネルへのメッセージの投稿は "Send chatMessage in channel" API をユーザー委任権限で実行します。
Graph API によるアプリケーション許可権限でのメッセージの送信は、他のサードパーティ製品からメッセージを移行する場合のみ行うことができます。
(参考:チャネルで chatMessage を送信する)
https://learn.microsoft.com/ja-jp/graph/api/channel-post-messages?view=graph-rest-1.0&tabs=http
アプリケーションのアクセス許可は 、移行でのみサポートされます。
- アクセス許可を指定してサインイン
# ダイアログが表示されたらメッセージを投稿するチームに所属するユーザーでサインインしてください Connect-MgGraph -Scopes "Team.ReadBasic.All", "ChannelSettings.Read.All"
- テスト用チームの ID を取得
# チームの名前を指定して実行してください Get-MgTeam -Filter "DisplayName eq 'テストチーム01'" | select Id, DisplayName
Id DisplayName -- ----------- d4923767-ea0d-4168-9422-108464d47b6d テストチーム01
- テスト用チャネルの ID を取得
# テスト用チームの ID を指定して実行してください Get-MgTeamChannel -TeamId "d4923767-ea0d-4168-9422-108464d47b6d" | select Id, DisplayName
Id DisplayName -- ----------- 19:SSOzOEGtTCpZ9TgVSlyqlAz3GbGHAkoySC7BfOsk1xU1@thread.tacv2 テストチャネル01
- テスト用チャネルに 1,000 件メッセージを送信
Connect-MgGraph -Scopes "ChannelMessage.Send" # テスト用チームの ID を指定してください $teamId = "d4923767-ea0d-4168-9422-108464d47b6d" # テスト用チャネルの ID を指定してください $channelId = "19:SSOzOEGtTCpZ9TgVSlyqlAz3GbGHAkoySC7BfOsk1xU1@thread.tacv2" # テスト用チャネルにテストメッセージを 1,000 件送信します for ($i = 1; $i -le 1000; $i++) { $params = @{ body = @{ # 送信するメッセージの内容を指定します content = "テスト メッセージ:$i" } } # Send chatMessage in channel API を使用してチャネルにメッセージを送信します New-MgTeamChannelMessage -TeamId $TeamId -ChannelId $ChannelId -BodyParameter $params # Invoke-MgGraphRequest コマンドの場合は以下のように実行します # Invoke-MgGraphRequest -Method POST -Uri "/v1.0/teams/$TeamId/channels/$ChannelId/messages" -Body $params -OutputType PSObject # API のスロットリングによる制限のため 1 秒ごとに 1 件のメッセージを送信します Sleep 1 }
※ 実行結果の例
スロットリングについて
Graph API で特定のチャネルに対してメッセージを送信する場合、1 秒間に 1 回 (1 RPS) メッセージを送信することができます。
上限を超えて実行すると、スロットリングによるエラーが返されます。
スロットリングについての詳細はこちら
Graph API では、1 秒間に実行できるリクエストの回数 (Request Per Seconds: RPS) に上限が定められています。上限を超えて Graph API を実行した場合、以下のようなエラーが返されます。
※ スロットリングによるエラーの例
{
"error": {
"code": "TooManyRequests",
"message": "{\"errorCode\":429,\"message\":\"API calls quota exceeded! 10Per10Secs\",\"standardizedError\":{\"errorCode\":429,\"errorSubCode\":1,\"errorDescription\":\"API calls quota exceeded! 10Per10Secs\"}}",
"innerError": {
"date": "2025-06-12T04:04:02",
"request-id": "8c38680d-9912-4a5d-822d-ff6a3bbbdfa7",
"client-request-id": "17eb0b4a-922e-4d67-9362-58e67726a25b"
}
}
}
RPS の上限は Graph API ごとに異なります。
(参考:Microsoft Teams サービスの制限)
https://learn.microsoft.com/ja-jp/graph/throttling-limits
特定のチャットまたはチャネルで POST メッセージを実行するときに、ユーザーごとに 1 秒あたり最大 1 つの要求を発行できます
エクスポート API の実行
あらかじめ "ChannelMessage.Read.All" アプリケーション許可権限を追加して Connect-MgGraph コマンドを実行しておきます。
※ 参考
メッセージの取得
-
評価モードでメッセージを取得
# テスト用チームの ID を指定してください $TeamId = "d4923767-ea0d-4168-9422-108464d47b6d" # チャネルメッセージ エクスポート API の URI を指定します # "model" パラメータは指定せずに評価モードで実行します $Uri = "/v1.0/teams/$TeamId/channels/getAllMessages" $response = Invoke-MgGraphRequest -Method GET -Uri $Uri -OutputType PSObject # 取得したメッセージを表示します $response.value | select body # 取得したメッセージの件数を表示します $response.value.length
- 10 件のメッセージが取得されました
body ---- @{contentType=text; content=テスト メッセージ:1} @{contentType=text; content=テスト メッセージ:2} @{contentType=text; content=テスト メッセージ:3} @{contentType=text; content=テスト メッセージ:5} @{contentType=text; content=テスト メッセージ:6} @{contentType=text; content=テスト メッセージ:4} @{contentType=text; content=テスト メッセージ:7} @{contentType=text; content=テスト メッセージ:8} @{contentType=text; content=テスト メッセージ:9} @{contentType=text; content=テスト メッセージ:10} 10
-
取得されたメッセージの詳細情報を確認
$response.value[0]
id : 1750209634494 replyToId : etag : 1750209634494 messageType : message createdDateTime : 2025/06/18 1:20:34 lastModifiedDateTime : 2025/06/18 1:20:34 lastEditedDateTime : deletedDateTime : subject : summary : chatId : importance : normal locale : en-us webUrl : https://teams.microsoft.com/l/message/19%3AQgQEUFxqWRzg7F1kNlPx86DBGHifIs__vsr8kcN87JE1%40thread .tacv2/1750209634494?groupId=05683739-7108-43f8-ab99-3754a7fbd82d&tenantId=8d6d6649-4030-4e9f-a6 cb-7e1443e7af6b&createdTime=1750209634494&parentMessageId=1750209634494 policyViolation : eventDetail : from : @{application=; device=; user=} body : @{contentType=text; content=テスト メッセージ:1} channelIdentity : @{teamId=05683739-7108-43f8-ab99-3754a7fbd82d; channelId=19:QgQEUFxqWRzg7F1kNlPx86DBGHifIs__vsr8 kcN87JE1@thread.tacv2} attachments : {} mentions : {} reactions : {}
取得されたメッセージには以下のような情報が含まれています。
- 投稿日時 (createdDateTime)
- 投稿者 (from)
- 件名 (subject)
- 本文 (body)
- チーム / チャネルの ID (channelIdentity)
- 添付ファイル (attachments)
- メンション (mentions)
- リアクション (reactions)
- URI に "$top=1000" を追加してメッセージを取得
# テスト用チームの ID を指定してください $TeamId = "d4923767-ea0d-4168-9422-108464d47b6d" # チャネルメッセージ エクスポート API の URI で "$top" パラメータを指定します $Uri = "/v1.0/teams/$TeamId/channels/getAllMessages?`$top=1000" $response = Invoke-MgGraphRequest -Method GET -Uri $Uri -OutputType PSObject # 取得したメッセージを表示します $response.value | select body # 取得したメッセージの件数を表示します $response.value.length
- 1,000 件のメッセージがすべて取得されました
body ---- @{contentType=text; content=テスト メッセージ:1} @{contentType=text; content=テスト メッセージ:2} @{contentType=text; content=テスト メッセージ:3} ... @{contentType=text; content=テスト メッセージ:1000} 1000
CSV ファイルへ出力
- 取得したメッセージを CSV ファイルへ出力するコマンド例です
# CSV ファイルの出力先を指定してください
$FilePath = "C:\Temp\messages.csv"
# 取得したメッセージを Export-Csv コマンドで CSV ファイルへ出力します
$response.value | select id,replyToId,createdDateTime,lastEditedDateTime,deletedDateTime,@{Name="fromUser"; Expression={$_.from.user.displayName}},messageType,subject,@{Name="bodyContent"; Expression={$_.body.content}},webUrl | Export-Csv -Path $FilePath -NoTypeInformation -Encoding UTF8
※ 出力結果のサンプル
"id","replyToId","createdDateTime","lastEditedDateTime","deletedDateTime","fromUser","messageType","subject","bodyContent","webUrl"
"1749101186629",,"2025/06/05 5:26:26",,,"テスト ユーザー01","message",,"テスト メッセージ:1","https://teams.microsoft.com/l/message/19%3ASSOzOEGtTCpZ9TgVSlyqlAz3GbGHAkoySC7BfOsk1xU1%40thread.tacv2/1749101186629?groupId=d4923767-ea0d-4168-9422-108464d47b6d&tenantId=ac2852a6-88d6-4ddc-9a63-93391e191144&createdTime=1749101186629&parentMessageId=1749101186629"
"1749101187126",,"2025/06/05 5:26:27",,,"テスト ユーザー01","message",,"テスト メッセージ:2","https://teams.microsoft.com/l/message/19%3ASSOzOEGtTCpZ9TgVSlyqlAz3GbGHAkoySC7BfOsk1xU1%40thread.tacv2/1749101187126?groupId=d4923767-ea0d-4168-9422-108464d47b6d&tenantId=ac2852a6-88d6-4ddc-9a63-93391e191144&createdTime=1749101187126&parentMessageId=1749101187126"
"1749101187452",,"2025/06/05 5:26:27",,,"テスト ユーザー01","message",,"テスト メッセージ:3","https://teams.microsoft.com/l/message/19%3ASSOzOEGtTCpZ9TgVSlyqlAz3GbGHAkoySC7BfOsk1xU1%40thread.tacv2/1749101187452?groupId=d4923767-ea0d-4168-9422-108464d47b6d&tenantId=ac2852a6-88d6-4ddc-9a63-93391e191144&createdTime=1749101187452&parentMessageId=1749101187452"
...
取得件数と処理時間
一度のリクエストで取得するメッセージの件数は "$top" パラメータで指定することができます。
取得件数が 250 件以下の場合には、1 秒ほどでメッセージを取得することができました。250 件を超えるとメッセージを取得するのに数秒かかりました。
取得件数 | 処理時間 |
---|---|
10 件 | 0.4 秒 |
100 件 | 1 秒 |
250 件 | 1.6 秒 |
500 件 | 3.1 秒 |
1000 件 | 6.7 秒 |
250 件を超えるメッセージを取得する際には、公開情報に記載されているとおり $top=250 を指定してページングによって繰り返し取得すると、効率よく処理できるようです。
(参考:Teams エクスポート API でサポートされる内容)
https://learn.microsoft.com/ja-jp/microsoftteams/export-teams-content#what-is-supported-by-the-teams-export-apis
Teams Meesage の上位制限: Teams メッセージ API の TOP フィルター制限は、パフォーマンスが制限される上限として 250 に設定することをお勧めします。
※ Invoke-MgGraphRequest コマンドでページングによってメッセージを取得するスクリプトの例です。
# テスト用チームの ID を指定してください
$TeamId = "d4923767-ea0d-4168-9422-108464d47b6d"
# チャネルメッセージ エクスポート API の URI で "$top" パラメータを指定します
$Uri = "/v1.0/teams/$TeamId/channels/getAllMessages?`$top=250"
# Invoke-MgGraphRequest でページング処理を行うコマンド(関数) です
Function Invoke-MgGraphRequestWithPaging($Method, $Uri, $OutputType) {
$responses = @()
$response = Invoke-MgGraphRequest -Method $Method -Uri $Uri -OutputType $OutputType
$responses += $response
# ページング処理を行います
# '@odata.nextLink' が返されなくなるまで情報を取得します
while($response.'@odata.nextLink' -ne $null){
$nextLink = $response.'@odata.nextLink'
$response = Invoke-MgGraphRequest -Method "GET" -Uri $nextLink -OutputType $OutputType
$responses += $response
}
# 取得したレスポンスをすべて返します
return $responses
}
# ページングによって 250 件ずつメッセージを取得します
$responses = Invoke-MgGraphRequestWithPaging -Method GET -Uri $Uri -OutputType PSObject
# 取得したメッセージを表示します
$responses | % {$_.value | select body}
# 取得したメッセージの件数を表示します
$responses | % {$_.value.length}
補足
無料枠を使い切った場合
評価版や支払いモデル A の無料枠をすべて消費した場合には、以下のような応答が返されメッセージを取得することができなくなります。
無料枠はアプリケーションごとため、別の Entra ID アプリケーションを使用して API を実行すれば再度無料枠を利用できます。
HTTP/1.1 402 Payment Required
{
"error": {
"code": "PaymentRequired",
"message": "Evaluation capacity for the month has exceeded. To continue beyond the evaluation limits complete billing onboarding. Visit https://docs.microsoft.com/en-us/graph/teams-licenses for API specific requirements.",
"innerError": {
"date": "2025-06-06T01:52:24",
"request-id": "29a5cf79-69eb-4134-a472-575fdb529daa",
"client-request-id": "53ca74b4-920c-4117-89d7-c12d488d2168"
}
}
}
支払いモデル A / B の従量課金を有効にする場合
従量課金を有効化は Azure ポータルから行います。
- 右上のボタンから Azure Cloud Shell を開き、[Bash] をクリックします
- 従量課金で使用する Azure サブスクリプションを選択し、[適用] をクリックします
- Aure Cloud Shell へ以下のコマンドを入力して実行します
※ 以下はリソースグループも同時に作成する場合の実行例です
resource_group=<リソースグループ名> resource_name=<任意のリソース名> subscription_id=<Azure サブスクリプション ID> application_clientid=<Entra アプリケーションの ClientID> az graph-services account create --resource-group $resource_group --resource-name $resource_name --subscription $subscription_id --location global --app-id $application_clientid
resource_group=testRG resource_name=testGraphAppBilling subscription_id=d6cc086c-b4fd-4bc1-b3e9-f14b601a792b application_clientid=3649c339-9b40-4e08-b36c-804b509890a8 # リソースグループも新規に作成する az group create -l japaneast -n $resource_group az graph-services account create --resource-group $resource_group --resource-name $resource_name --subscription $subscription_id --location global --app-id $application_clientid
-
"provisioningState" : "Succeeded" と表示されたら完了です
従量課金を無効化する場合
従量課金を無効化するには以下のコマンドを実行します。
az graph-services account delete --resource-group $resource_group --resource-name $resource_name --subscription $subscription_id
(参考:Microsoft Graph で従量制課金 API とサービスを有効にする)
https://learn.microsoft.com/ja-jp/graph/metered-api-setup
(参考:az graph-services account)
https://learn.microsoft.com/ja-jp/cli/azure/graph-services/account?view=azure-cli-latest#az-graph-services-account-delete