Just another IT site ※IT系の記事は当方環境での実施内容となるため実施する場合は自己責任でお願いいたします。At Your Own Risk!! TURN BACK WHILE YOU CAN
PR

パスワード認証を使用するメールの重要通知をOpenClaw経由でDiscordへ送る手順【AI作成手順 未検証】

※IT系の記事は当方環境での実施内容となるため実施する場合は自己責任でお願いいたします。スクリプトはAI生成のものも多いのでコピー&ペーストの際は文字コードに注意ください!
スポンサーリンク
バッチ処理の自動化スキルは市場価値が高いです。今の自分の単価を調べてみませんか?
顧客常駐はもう嫌だ!社内SEへ転職するなら【社内SE転職ナビ】
Cursor・Claude Code・Codex AIスキルを学ぶなら
環境構築不要!AIエージェント開発を非エンジニアでも即実践【AI Agent Camp】

パスワード認証を使用するメールの重要通知をOpenClaw経由でDiscordへ送る構成

パスワード認証を使用するメールアカウントに届いたメールをUbuntuサーバで確認し、特定のキーワードを含むメールだけをOpenClaw経由でDiscordへ通知する手順をまとめます。

Microsoft 365版ではMicrosoft Graph APIとOAuth2を使いましたが、パスワード認証を使用するメール版では一般的なIMAP受信を使います。OAuth2ではなくメールアカウントの認証情報を扱うため、パスワード管理を慎重に行う必要があります。

メールサービス
  ↓ IMAP over SSL/TLS
Ubuntuサーバ
  ↓ メール取得スクリプト
キーワード判定
  ↓
OpenClaw CLI
  ↓
Discordチャンネル通知

メールサービス側でIMAP設定を確認する

まず、パスワード認証メールの管理画面やメール設定画面で、IMAP接続に必要な情報を確認します。

  • IMAPサーバ名
  • IMAPポート番号
  • SSL/TLSの有無
  • メールアドレス
  • メールパスワード

一般的には、IMAP over SSL/TLSを使う場合のポートは 993 です。ただし、実際のサーバ名や設定値は契約中の利用中のメールサービスの管理画面に表示されている内容を使います。

通知専用メールアカウントを用意する

可能であれば、普段使いの個人メールアカウントではなく、通知監視専用のメールアカウントを用意します。

監視専用アカウントにしておくと、パスワード漏えい時の影響範囲を小さくできます。また、通知対象のメールだけを転送する運用にすると、Discordへ流す情報も最小限にできます。

Ubuntu側に必要なパッケージを入れる

Ubuntu側では、PythonでIMAP接続とメール解析を行います。

sudo apt update
sudo apt install -y python3

標準ライブラリの imaplibemailssl を使うため、追加のPythonパッケージは必須ではありません。

Ubuntu側に設定ファイルを作成する

メールパスワードはOpenClawのワークスペースやWeb公開ディレクトリには置かず、rootだけが読める設定ファイルに保存します。以下のパスは例です。

sudo install -m 600 -o root -g root /dev/null /etc/example-password-auth-mail-watcher.env
sudo nano /etc/example-password-auth-mail-watcher.env

設定ファイルの例です。実際の値は環境に合わせて置き換えます。

IMAP_HOST="imap.example.jp"
IMAP_PORT="993"
IMAP_USER="mailbox@example.com"
IMAP_PASSWORD="dummy-mail-password"

KEYWORDS="障害|緊急|至急|アラート|エラー"

OPENCLAW_NOTIFY_TARGET="channel:123456789012345678"

OPENCLAW_NOTIFY_TARGET には、通知したいDiscordチャンネルIDを指定します。

状態保存用ディレクトリを作成する

同じメールを何度も通知しないよう、処理済みメールのUIDを保存するディレクトリを作成します。

sudo install -d -m 700 -o root -g root /var/lib/example-password-auth-mail-watcher

メール取得とキーワード判定スクリプトを作成する

IMAPでメールを取得し、件名や本文にキーワードが含まれる場合だけDiscordへ通知するスクリプトを作成します。以下のパスは例です。

sudo nano /usr/local/bin/example-password-auth-mail-watcher.py

スクリプト例です。

#!/usr/bin/env python3
import email
import imaplib
import os
import re
import ssl
import subprocess
from email.header import decode_header
from email.message import Message


ENV_FILE = "/etc/example-password-auth-mail-watcher.env"
STATE_FILE = "/var/lib/example-password-auth-mail-watcher/seen_uids.txt"


def load_env(path):
    values = {}
    with open(path, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith("#") or "=" not in line:
                continue
            key, value = line.split("=", 1)
            values[key] = value.strip().strip('"').strip("'")
    return values


def decode_mime(value):
    if not value:
        return ""
    parts = []
    for text, charset in decode_header(value):
        if isinstance(text, bytes):
            parts.append(text.decode(charset or "utf-8", errors="replace"))
        else:
            parts.append(text)
    return "".join(parts)


def extract_text(message: Message):
    if message.is_multipart():
        chunks = []
        for part in message.walk():
            content_type = part.get_content_type()
            disposition = str(part.get("Content-Disposition") or "")
            if "attachment" in disposition.lower():
                continue
            if content_type == "text/plain":
                payload = part.get_payload(decode=True)
                if payload:
                    charset = part.get_content_charset() or "utf-8"
                    chunks.append(payload.decode(charset, errors="replace"))
        return "\n".join(chunks)

    payload = message.get_payload(decode=True)
    if not payload:
        return ""
    charset = message.get_content_charset() or "utf-8"
    return payload.decode(charset, errors="replace")


def load_seen_uids(path):
    if not os.path.exists(path):
        return set()
    with open(path, "r", encoding="utf-8") as f:
        return set(line.strip() for line in f if line.strip())


def save_seen_uids(path, seen):
    with open(path, "w", encoding="utf-8") as f:
        for uid in sorted(seen, key=lambda x: int(x) if x.isdigit() else x):
            f.write(uid + "\n")


def send_discord(target, matched_lines):
    message = "パスワード認証メール キーワード一致: {}件\n\n{}".format(
        len(matched_lines),
        "\n".join(matched_lines),
    )
    subprocess.run(
        [
            "openclaw",
            "message",
            "send",
            "--channel",
            "discord",
            "--target",
            target,
            "--message",
            message,
        ],
        check=True,
    )


def main():
    env = load_env(ENV_FILE)
    host = env["IMAP_HOST"]
    port = int(env.get("IMAP_PORT", "993"))
    user = env["IMAP_USER"]
    password = env["IMAP_PASSWORD"]
    keywords = env["KEYWORDS"]
    notify_target = env["OPENCLAW_NOTIFY_TARGET"]

    keyword_re = re.compile(keywords, re.IGNORECASE)
    seen = load_seen_uids(STATE_FILE)
    matched = []

    context = ssl.create_default_context()
    with imaplib.IMAP4_SSL(host, port, ssl_context=context) as client:
        client.login(user, password)
        client.select("INBOX")

        status, data = client.uid("search", None, "ALL")
        if status != "OK":
            raise RuntimeError("IMAP search failed")

        uids = data[0].decode().split()
        for uid in uids[-50:]:
            if uid in seen:
                continue

            status, msg_data = client.uid("fetch", uid, "(RFC822)")
            if status != "OK":
                continue

            raw = msg_data[0][1]
            msg = email.message_from_bytes(raw)
            subject = decode_mime(msg.get("Subject"))
            from_addr = decode_mime(msg.get("From"))
            body = extract_text(msg)

            if keyword_re.search(subject) or keyword_re.search(body):
                matched.append("- From: {}\n  件名: {}".format(from_addr, subject or "(no subject)"))

            seen.add(uid)

        client.logout()

    if matched:
        send_discord(notify_target, matched)

    save_seen_uids(STATE_FILE, seen)


if __name__ == "__main__":
    main()

スクリプトに実行権限を付けます。

sudo chmod 700 /usr/local/bin/example-password-auth-mail-watcher.py

OpenClawからDiscord通知できるか確認する

先にOpenClaw経由でDiscordへ通知できることを確認します。チャンネルIDはダミーです。

openclaw message send \
  --channel discord \
  --target channel:123456789012345678 \
  --message "メール通知テスト"

通知できれば、次にメール取得スクリプトを手動実行します。

sudo /usr/local/bin/example-password-auth-mail-watcher.py

systemd serviceを作成する

手動実行で問題がなければ、systemd serviceを作成します。

sudo nano /etc/systemd/system/example-password-auth-mail-watcher.service
[Unit]
Description=Watch password-auth mail and notify Discord via OpenClaw

[Service]
Type=oneshot
ExecStart=/usr/local/bin/example-password-auth-mail-watcher.py

systemd timerを作成する

5分ごとに実行するtimerを作成します。

sudo nano /etc/systemd/system/example-password-auth-mail-watcher.timer
[Unit]
Description=Run password-auth mail watcher periodically

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Persistent=true

[Install]
WantedBy=timers.target

timerを有効化します。

sudo systemctl daemon-reload
sudo systemctl enable --now example-password-auth-mail-watcher.timer

動作確認を行う

timerの状態と実行ログを確認します。

systemctl list-timers example-password-auth-mail-watcher.timer
journalctl -u example-password-auth-mail-watcher.service -n 50 --no-pager

テスト用にキーワードを含むメールを対象メールボックスへ送り、Discordに通知されることを確認します。

通知内容は最小限にする

Discordへ通知する内容は、必要最小限にするのが安全です。本文全文や添付ファイルをそのまま流すと、情報漏えいのリスクが上がります。

最初は次の程度に抑えるのがよいです。

  • 検出件数
  • 送信者
  • 件名
  • 一致したキーワード

運用時の注意点

  • メールパスワードはOpenClawワークスペースに置かない
  • 設定ファイルはrootのみ読める権限にする
  • IMAPはSSL/TLSで接続する
  • 可能なら通知専用メールアカウントを使う
  • Discordには本文全文や添付ファイルを流さない
  • ログにメールパスワードや本文を出さない
  • 同じメールを何度も通知しないようUIDを保存する
  • 最初は5分間隔程度で運用する

Microsoft 365版との違い

Microsoft 365版では、Microsoft Graph APIとOAuth2を使ってメールを取得します。一方、パスワード認証を使用するメール版ではIMAP over SSL/TLSを使います。

パスワード認証を使用するメール版は構成がシンプルですが、メールパスワードをサーバに保存する必要があります。そのため、専用アカウントを使い、設定ファイルの権限を厳しく制限することが重要です。

まとめ

パスワード認証を使用するメールの重要通知をDiscordへ通知するには、UbuntuサーバからIMAP over SSL/TLSでメールを取得し、件名や本文に特定キーワードが含まれている場合だけOpenClaw CLIでDiscordへ通知する構成が実用的です。

Microsoft 365版より設定は簡単ですが、OAuth2ではなくメールパスワードを扱うため、パスワード管理と通知内容の最小化が重要です。


タイトルとURLをコピーしました