Microsoft 365の重要メールをOpenClaw経由でDiscord通知する構成
Microsoft 365のメールをUbuntuサーバで安全に取得し、特定のキーワードを含むメールが届いたときだけ、OpenClaw経由で任意のDiscordチャンネルへ通知する構成をまとめます。
この構成では、Microsoft 365の通常パスワードやBasic認証は使いません。Microsoft Graph APIとOAuth2を使ってメールを取得し、Ubuntu側のスクリプトでキーワード判定を行います。
Microsoft 365 / Exchange Online
↓
Microsoft Graph API + OAuth2
↓
Ubuntuサーバ
↓
キーワード判定スクリプト
↓
OpenClaw CLI
↓
Discordチャンネル通知
Microsoft 365側でアプリを登録する
まず、Microsoft Entra管理センターでGraph API用のアプリを登録します。
- Microsoft Entra管理センターを開く
- 「アプリの登録」を開く
- 「新規登録」を選択する
- 名前を入力する。例:
openclaw-mail-watcher - 対応アカウントは通常「この組織のディレクトリのみ」を選択する
- 登録後、
Tenant IDとClient IDを控える
クライアントシークレットを作成する
アプリ登録後、「証明書とシークレット」からクライアントシークレットを作成します。最初はクライアントシークレットで始めても構いませんが、長期運用では証明書認証の方が安全です。
控える値は次の3つです。
TENANT_ID
CLIENT_ID
CLIENT_SECRET
クライアントシークレットは作成直後しか値を確認できません。紛失した場合は再作成します。
Graph APIの権限を付与する
アプリにMicrosoft Graphの権限を付与します。サーバから無人でメールを読む場合は、通常はアプリケーション権限を使います。
Microsoft Graph
Application permissions
Mail.Read
権限を追加したら、管理者の同意を付与します。
Mail.Read は強い権限です。次の手順で、読めるメールボックスを必ず制限します。
読めるメールボックスを制限する
Graph APIのアプリケーション権限は、そのままだと広い範囲のメールボックスを読める可能性があります。Exchange Online側で、対象メールボックスだけに制限します。
例として、メール許可用のグループに対象メールボックスを入れ、そのグループに対してアプリのアクセスを制限します。
Connect-ExchangeOnline
New-ApplicationAccessPolicy `
-AppId "00000000-0000-0000-0000-000000000000" `
-PolicyScopeGroupId "graph-mail-readers@example.com" `
-AccessRight RestrictAccess `
-Description "Allow OpenClaw mail watcher to read approved mailboxes only"
Test-ApplicationAccessPolicy `
-Identity "mailbox@example.com" `
-AppId "00000000-0000-0000-0000-000000000000"
Test-ApplicationAccessPolicy の結果が許可になっていることを確認します。
Ubuntu側に必要なパッケージを入れる
Ubuntu側では、HTTPリクエスト用の curl とJSON処理用の jq を使います。
sudo apt update
sudo apt install -y curl jq
Ubuntu側に設定ファイルを作成する
認証情報はOpenClawのワークスペースやWeb公開ディレクトリには置かず、rootだけが読める場所に保存します。以下のパスは例です。
sudo install -m 600 -o root -g root /dev/null /etc/example-m365-mail-watcher.env
sudo nano /etc/example-m365-mail-watcher.env
設定ファイルの例です。実際の値は環境に合わせて置き換えます。
TENANT_ID="00000000-0000-0000-0000-000000000000"
CLIENT_ID="11111111-1111-1111-1111-111111111111"
CLIENT_SECRET="dummy-client-secret"
MAILBOX="mailbox@example.com"
KEYWORDS="障害|緊急|至急|アラート|エラー"
OPENCLAW_NOTIFY_TARGET="channel:123456789012345678"
OPENCLAW_NOTIFY_TARGET には、通知したいDiscordチャンネルIDを指定します。
状態保存用ディレクトリを作成する
同じメールを何度も通知しないよう、最後に確認したメールの日時を保存します。
sudo install -d -m 700 -o root -g root /var/lib/example-m365-mail-watcher
メール取得とキーワード判定スクリプトを作成する
次に、Microsoft Graph APIでメールを取得し、件名や本文プレビューにキーワードが含まれているか判定するスクリプトを作成します。以下のパスは例です。
sudo nano /usr/local/bin/example-m365-mail-watcher.sh
スクリプト例です。
#!/usr/bin/env bash
set -euo pipefail
source /etc/example-m365-mail-watcher.env
STATE_DIR="/var/lib/example-m365-mail-watcher"
LAST_FILE="${STATE_DIR}/last_received.txt"
LAST_RECEIVED="1970-01-01T00:00:00Z"
if [[ -f "${LAST_FILE}" ]]; then
LAST_RECEIVED="$(cat "${LAST_FILE}")"
fi
TOKEN=$(
curl -s -X POST "https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}" \
-d "scope=https://graph.microsoft.com/.default" \
-d "grant_type=client_credentials" |
jq -r '.access_token'
)
if [[ -z "${TOKEN}" || "${TOKEN}" == "null" ]]; then
echo "failed to get access token" >&2
exit 1
fi
URL="https://graph.microsoft.com/v1.0/users/${MAILBOX}/mailFolders/Inbox/messages?\$top=10&\$orderby=receivedDateTime desc&\$select=id,subject,from,receivedDateTime,bodyPreview,webLink"
RESPONSE=$(
curl -s "${URL}" \
-H "Authorization: Bearer ${TOKEN}"
)
NEW_ITEMS=$(
echo "${RESPONSE}" |
jq --arg last "${LAST_RECEIVED}" --arg re "${KEYWORDS}" '
[
.value[]?
| select(.receivedDateTime > $last)
| select(
((.subject // "") | test($re; "i"))
or
((.bodyPreview // "") | test($re; "i"))
)
]
| sort_by(.receivedDateTime)
'
)
COUNT=$(echo "${NEW_ITEMS}" | jq 'length')
if [[ "${COUNT}" -gt 0 ]]; then
MESSAGE=$(
echo "${NEW_ITEMS}" |
jq -r '
"Microsoft 365 キーワード一致メール: " + (length|tostring) + "件\n\n" +
(
map(
"- 日時: " + (.receivedDateTime // "") + "\n" +
" From: " + (.from.emailAddress.address // "(unknown)") + "\n" +
" 件名: " + (.subject // "(no subject)") + "\n"
) | join("\n")
)
'
)
openclaw message send \
--channel discord \
--target "${OPENCLAW_NOTIFY_TARGET}" \
--message "${MESSAGE}" \
>/dev/null
fi
NEW_LAST=$(
echo "${RESPONSE}" |
jq -r '[.value[]?.receivedDateTime] | max // empty'
)
if [[ -n "${NEW_LAST}" ]]; then
printf '%s\n' "${NEW_LAST}" > "${LAST_FILE}"
fi
スクリプトに実行権限を付けます。
sudo chmod 700 /usr/local/bin/example-m365-mail-watcher.sh
OpenClawからDiscord通知できるか確認する
先にOpenClaw経由でDiscordへ通知できることを確認します。チャンネルIDはダミーです。
openclaw message send \
--channel discord \
--target channel:123456789012345678 \
--message "Microsoft 365メール通知テスト"
通知できれば、次にメール取得スクリプトを手動実行します。
sudo /usr/local/bin/example-m365-mail-watcher.sh
systemd serviceを作成する
手動実行で問題がなければ、systemd serviceを作成します。
sudo nano /etc/systemd/system/example-m365-mail-watcher.service
[Unit]
Description=Watch Microsoft 365 mail and notify Discord via OpenClaw
[Service]
Type=oneshot
ExecStart=/usr/local/bin/example-m365-mail-watcher.sh
systemd timerを作成する
5分ごとに実行するtimerを作成します。
sudo nano /etc/systemd/system/example-m365-mail-watcher.timer
[Unit]
Description=Run Microsoft 365 mail watcher periodically
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Persistent=true
[Install]
WantedBy=timers.target
timerを有効化します。
sudo systemctl daemon-reload
sudo systemctl enable --now example-m365-mail-watcher.timer
動作確認を行う
timerの状態と実行ログを確認します。
systemctl list-timers example-m365-mail-watcher.timer
journalctl -u example-m365-mail-watcher.service -n 50 --no-pager
テスト用にキーワードを含むメールを対象メールボックスへ送り、Discordに通知されることを確認します。
通知内容は最小限にする
Discordに通知する内容は、必要最小限にするのが安全です。本文全文や添付ファイルをそのまま流すと、情報漏えいのリスクが上がります。
通知内容は、まず次の程度に抑えるのがよいです。
- 検出日時
- 送信者
- 件名
- 一致したキーワード
- 必要であればメールへのリンク
運用時の注意点
- Microsoft 365の通常パスワードはUbuntuに保存しない
- Basic認証のIMAPやPOPは使わない
- Graph APIとOAuth2を使う
- クライアントシークレットはrootのみ読める場所に保存する
- 可能であれば証明書認証に移行する
- Graph APIの権限は必要最小限にする
- 対象メールボックスを必ず制限する
- ログにアクセストークンやメール本文を出さない
- Discordには本文全文や添付ファイルを流さない
- 通知間隔は最初は5分程度で十分
まとめ
Microsoft 365のメールを安全に監視してDiscordへ通知するには、Microsoft Graph APIとOAuth2を使う構成が適しています。
Microsoft 365側ではアプリ登録、Graph API権限、メールボックス制限を行います。Ubuntu側では、Graph APIでメールを取得するスクリプトを作成し、件名や本文プレビューに特定キーワードが含まれている場合だけ、OpenClaw CLIで任意のDiscordチャンネルへ通知します。
この構成にすると、Microsoft 365のパスワードをサーバに保存せず、必要なメールだけを安全に検出して、Discordへ自動通知できます。