Microsoft Teams 通知

にメンテナンス済み

kintone のデータを Microsoft Teams に通知することで、レコードの追加・更新・ステータス変更などの重要なイベントをチームにリアルタイムで共有できます。

kintone には Slack との標準連携機能がありますが、Microsoft Teams との連携は標準機能としては提供されていません。しかし、Teams の Incoming Webhook(Workflows 経由)と kintone の kintone.proxy を組み合わせることで、カスタマイズによる通知連携が実現できます。

この記事では、Teams への通知送信の基本から、リッチな Adaptive Card の活用、実践的な自動通知パターンまで解説します。

Slack - 通知の送信
kintone の JavaScript カスタマイズから Slack に通知を送る方法を解説します。Incoming Webhook を使った基本的な通知の送信から、レコード情報を含むリッチな通知、レコード保存時の自動通知まで紹介します。

Teams の Incoming Webhook を設定する

Microsoft Teams に外部からメッセージを送信するには、Workflows(旧 Incoming Webhook コネクタ)を利用します。

設定手順

  1. Microsoft Teams で通知を受け取りたいチャネルを開く
  2. チャネルの「」メニュー → 「ワークフロー」を選択
  3. Webhook 要求を受信したときにチャネルに投稿する」テンプレートを選択
  4. ワークフロー名を入力し、投稿先のチャネルを確認して「追加」をクリック
  5. 生成された Webhook URL をコピーする
Webhook URL の管理

Webhook URL には認証情報が含まれています。URL が漏洩するとチャネルに不正なメッセージが投稿される可能性があるため、コード中に直接記載することは避け、安全に管理してください。

旧コネクタからの移行

Microsoft 365 の Incoming Webhook コネクタは廃止予定です。新規作成する場合は Workflows(Power Automate ベース)を使用してください。既存のコネクタ URL は移行が必要な場合があります。

kintone からシンプルな通知を送信する

基本的な送信関数

kintone.proxy を使って、Teams の Webhook URL にメッセージを送信します。

send-teams-notification.js
/**
 * 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.proxy を使う理由

kintone のカスタマイズ JS から外部 API を直接呼び出すと、CORS(Cross-Origin Resource Sharing)制限によりリクエストがブロックされます。kintone.proxy を使うことで、kintone のサーバーを経由して外部 API にリクエストを送信でき、CORS 制限を回避できます。

kintone.proxyの使い方
kintone JavaScript カスタマイズから外部 API を呼び出す際に必要な kintone.proxy の使い方を解説します。GET/POST/PUT/DELETE の各メソッドの使い方、リクエストヘッダーの設定、レスポンスの

使用例

basic-notification.js
(() => {
  '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 を使うと、タイトル・本文・ボタンなどを含むリッチな通知を送信できます。

rich-notification.js
/**
 * 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})`);
  }
};

使用例:レコード情報を含む通知

rich-notification-usage.js
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 に通知を送信するパターンです。

auto-notify-on-save.js
(() => {
  '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 で通知するパターンです。

notify-on-status-change.js
(() => {
  '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;
  });
})();
プロセス管理のカスタマイズ
kintone のプロセス管理機能をJavaScriptカスタマイズで拡張する方法を解説します。ステータス変更イベントの活用、ステータスに応じたフィールド制御、プロセス管理 REST API によるステータス操作まで紹介します。

Webhook(サーバーサイド)との比較

kintone には Webhook 機能もあり、レコードの追加・更新・削除時に外部 URL にリクエストを送信できます。

比較項目kintone.proxy(クライアント)Webhook(サーバーサイド)
実行タイミングユーザーの画面操作時サーバーでのレコード変更時
API 経由のレコード変更通知されない通知される
中間サーバーの必要性不要必要(Webhook 受信 → Teams 送信)
通知内容のカスタマイズ高い自由度Webhook ペイロードに依存
ユーザー情報の取得getLoginUser() で取得可能ペイロードに含まれる
チェック

API 経由(GAS やバッチ処理)でレコードが更新されるケースも通知したい場合は、Webhook を使った通知がおすすめです。kintone.proxy はユーザーが画面上で操作した場合にのみ通知されます。

Webhook
kintone の Webhook 機能を使って、レコードの追加・更新・削除やステータス変更時に外部サービスへ自動通知する仕組みを解説します。Webhook の設定手順、受信側の実装例、セキュリティの考慮点まで紹介します。

まとめ

  • Microsoft Teams への通知は、Teams の Workflows(Incoming Webhook)と kintone.proxy で実現できる
  • kintone.proxy を使うことで、CORS 制限を回避して外部 API にリクエストを送信できる
  • Adaptive Card を使うと、タイトル・本文・ファクト情報・ボタンを含むリッチな通知を送信できる
  • submit.success イベントでレコード保存後に自動通知を実装する場合は、try-catch で通知エラーがレコード保存に影響しないようにする
  • API 経由のレコード変更も通知したい場合は、Webhook の併用を検討する

練習問題

kintone から Microsoft Teams に通知を送信する際、CORS 制限を回避するために使用する API はどれですか?

レコード保存後の自動通知で、通知処理のエラーがレコード保存に影響しないようにするにはどうしますか?

kintone.proxy ではなく Webhook を使用すべきケースはどれですか?
#kintone #JavaScript #Microsoft Teams