Microsoft Teams 通知
kintone のデータを Microsoft Teams に通知することで、レコードの追加・更新・ステータス変更などの重要なイベントをチームにリアルタイムで共有できます。
kintone には Slack との標準連携機能がありますが、Microsoft Teams との連携は標準機能としては提供されていません。しかし、Teams の Incoming Webhook(Workflows 経由)と kintone の kintone.proxy を組み合わせることで、カスタマイズによる通知連携が実現できます。
この記事では、Teams への通知送信の基本から、リッチな Adaptive Card の活用、実践的な自動通知パターンまで解説します。
Teams の Incoming Webhook を設定する
Microsoft Teams に外部からメッセージを送信するには、Workflows(旧 Incoming Webhook コネクタ)を利用します。
設定手順
- Microsoft Teams で通知を受け取りたいチャネルを開く
- チャネルの「⋯」メニュー → 「ワークフロー」を選択
- 「Webhook 要求を受信したときにチャネルに投稿する」テンプレートを選択
- ワークフロー名を入力し、投稿先のチャネルを確認して「追加」をクリック
- 生成された Webhook URL をコピーする
Webhook URL には認証情報が含まれています。URL が漏洩するとチャネルに不正なメッセージが投稿される可能性があるため、コード中に直接記載することは避け、安全に管理してください。
Microsoft 365 の Incoming Webhook コネクタは廃止予定です。新規作成する場合は Workflows(Power Automate ベース)を使用してください。既存のコネクタ URL は移行が必要な場合があります。
kintone からシンプルな通知を送信する
基本的な送信関数
kintone.proxy を使って、Teams の Webhook URL にメッセージを送信します。
/**
* Microsoft Teams に通知を送信する
* @param { string } webhookUrl - Teams の Webhook URL
* @param { string } message - 送信するメッセージ
* @returns { Promise<void> }
*/
const sendTeamsNotification = async (webhookUrl, message) => {
const body = {
type: 'message',
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
contentUrl: null,
content: {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
version: '1.4',
body: [
{
type: 'TextBlock',
text: message,
wrap: true,
},
],
},
},
],
};
const [responseBody, statusCode] = await kintone.proxy(
webhookUrl,
'POST',
{ 'Content-Type': 'application/json' },
body
);
if (statusCode !== 200 && statusCode !== 202) {
throw new Error(`Teams への通知に失敗しました(ステータス: ${statusCode})`);
}
};
kintone のカスタマイズ JS から外部 API を直接呼び出すと、CORS(Cross-Origin Resource
Sharing)制限によりリクエストがブロックされます。kintone.proxy を使うことで、kintone
のサーバーを経由して外部 API にリクエストを送信でき、CORS 制限を回避できます。
使用例
(() => {
'use strict';
const TEAMS_WEBHOOK_URL = 'https://xxx.webhook.office.com/webhookb2/...';
kintone.events.on(['app.record.detail.show'], async (event) => {
const space = kintone.app.record.getSpaceElement('notification-button');
if (!space) {
return event;
}
const button = document.createElement('button');
button.textContent = 'Teams に通知';
button.style.cssText = 'padding: 8px 16px; background: #6264a7; color: white; border: none; border-radius: 4px; cursor: pointer;';
button.addEventListener('click', async () => {
try {
const record = kintone.app.record.get().record;
const message = `📋 レコード #${record['レコード番号'].value} の確認をお願いします。`;
await sendTeamsNotification(TEAMS_WEBHOOK_URL, message);
alert('Teams に通知を送信しました');
} catch (error) {
console.error(error);
alert('通知の送信に失敗しました');
}
});
space.appendChild(button);
return event;
});
})();
Adaptive Card を使ったリッチ通知
Microsoft Teams の Adaptive Card を使うと、タイトル・本文・ボタンなどを含むリッチな通知を送信できます。
/**
* Adaptive Card 形式でリッチな通知を送信する
* @param { string } webhookUrl - Teams の Webhook URL
* @param { Object } params
* @param { string } params.title - 通知タイトル
* @param { string } params.message - 通知メッセージ
* @param { string } params.recordUrl - レコードのURL
* @param { Object[] } params.facts - 表示するファクト情報
* @returns { Promise<void> }
*/
const sendRichNotification = async (webhookUrl, params) => {
const { title, message, recordUrl, facts } = params;
const body = {
type: 'message',
attachments: [
{
contentType: 'application/vnd.microsoft.card.adaptive',
contentUrl: null,
content: {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
type: 'AdaptiveCard',
version: '1.4',
body: [
{
type: 'TextBlock',
text: title,
weight: 'Bolder',
size: 'Medium',
color: 'Accent',
},
{
type: 'TextBlock',
text: message,
wrap: true,
},
{
type: 'FactSet',
facts: facts.map((fact) => ({
title: fact.label,
value: fact.value,
})),
},
],
actions: recordUrl
? [
{
type: 'Action.OpenUrl',
title: 'kintone で確認する',
url: recordUrl,
},
]
: [],
},
},
],
};
const [responseBody, statusCode] = await kintone.proxy(
webhookUrl,
'POST',
{ 'Content-Type': 'application/json' },
body
);
if (statusCode !== 200 && statusCode !== 202) {
throw new Error(`Teams への通知に失敗しました(ステータス: ${statusCode})`);
}
};
使用例:レコード情報を含む通知
const record = event.record;
const appId = kintone.app.getId();
const recordId = record['レコード番号'].value;
const subdomain = location.hostname;
await sendRichNotification(TEAMS_WEBHOOK_URL, {
title: '🔔 新しい案件が登録されました',
message: '以下の案件が追加されています。確認をお願いします。',
recordUrl: `https://${subdomain}/k/${appId}/show#record=${recordId}`,
facts: [
{ label: '案件名', value: record['案件名'].value },
{ label: '顧客名', value: record['顧客名'].value },
{ label: '金額', value: `¥${Number(record['金額'].value).toLocaleString()}` },
{ label: '担当者', value: record['担当者'].value[0]?.name || '未設定' },
],
});
Adaptive Card の Action.OpenUrl を使うと、通知カード内に「kintone
で確認する」ボタンを追加できます。受信者がワンクリックで該当レコードを開けるため、業務効率が向上します。
実践パターン:レコード保存時の自動通知
レコードの追加や更新が成功した際に、自動的に Teams に通知を送信するパターンです。
(() => {
'use strict';
const TEAMS_WEBHOOK_URL = 'https://xxx.webhook.office.com/webhookb2/...';
const events = ['app.record.create.submit.success'];
kintone.events.on(events, async (event) => {
const record = event.record;
const appId = kintone.app.getId();
const recordId = event.recordId;
const subdomain = location.hostname;
const loginUser = kintone.getLoginUser();
try {
await sendRichNotification(TEAMS_WEBHOOK_URL, {
title: '📝 レコードが追加されました',
message: `${loginUser.name} さんが新しいレコードを追加しました。`,
recordUrl: `https://${subdomain}/k/${appId}/show#record=${recordId}`,
facts: [
{ label: 'アプリID', value: String(appId) },
{ label: 'レコード番号', value: String(recordId) },
{ label: '登録者', value: loginUser.name },
],
});
} catch (error) {
// 通知の失敗はレコード保存に影響させない
console.error('Teams 通知エラー:', error);
}
return event;
});
})();
submit.success
イベントはレコードの保存が成功した後に発火します。通知処理でエラーが発生しても、try-catch
でキャッチしてレコードの保存処理に影響を与えないようにしましょう。
実践パターン:ステータス変更時の通知
プロセス管理のステータスが変更された際に、次のアクション担当者に Teams で通知するパターンです。
(() => {
'use strict';
const TEAMS_WEBHOOK_URL = 'https://xxx.webhook.office.com/webhookb2/...';
const events = [
'app.record.detail.process.proceed',
'mobile.app.record.detail.process.proceed',
];
kintone.events.on(events, async (event) => {
const record = event.record;
const action = event.action.value;
const nextStatus = event.nextStatus.value;
const appId = kintone.app.getId();
const recordId = kintone.app.record.getId();
const subdomain = location.hostname;
const loginUser = kintone.getLoginUser();
try {
await sendRichNotification(TEAMS_WEBHOOK_URL, {
title: `🔄 ステータスが「${nextStatus}」に変更されました`,
message: `${loginUser.name} さんが「${action}」を実行しました。`,
recordUrl: `https://${subdomain}/k/${appId}/show#record=${recordId}`,
facts: [
{ label: '案件名', value: record['案件名'].value },
{ label: 'アクション', value: action },
{ label: '新しいステータス', value: nextStatus },
{ label: '実行者', value: loginUser.name },
],
});
} catch (error) {
console.error('Teams 通知エラー:', error);
}
return event;
});
})();
Webhook(サーバーサイド)との比較
kintone には Webhook 機能もあり、レコードの追加・更新・削除時に外部 URL にリクエストを送信できます。
| 比較項目 | kintone.proxy(クライアント) | Webhook(サーバーサイド) |
|---|---|---|
| 実行タイミング | ユーザーの画面操作時 | サーバーでのレコード変更時 |
| API 経由のレコード変更 | 通知されない | 通知される |
| 中間サーバーの必要性 | 不要 | 必要(Webhook 受信 → Teams 送信) |
| 通知内容のカスタマイズ | 高い自由度 | Webhook ペイロードに依存 |
| ユーザー情報の取得 | getLoginUser() で取得可能 | ペイロードに含まれる |
API 経由(GAS やバッチ処理)でレコードが更新されるケースも通知したい場合は、Webhook
を使った通知がおすすめです。kintone.proxy はユーザーが画面上で操作した場合にのみ通知されます。
まとめ
- Microsoft Teams への通知は、Teams の Workflows(Incoming Webhook)と
kintone.proxyで実現できる kintone.proxyを使うことで、CORS 制限を回避して外部 API にリクエストを送信できる- Adaptive Card を使うと、タイトル・本文・ファクト情報・ボタンを含むリッチな通知を送信できる
submit.successイベントでレコード保存後に自動通知を実装する場合は、try-catch で通知エラーがレコード保存に影響しないようにする- API 経由のレコード変更も通知したい場合は、Webhook の併用を検討する