メール通知Botで、送信成功後だけ既読にするようにした話
Gmailの未読メールをDiscordへ転送するBotを、GASからNode.jsへ作り直しました。
一見すると「未読を取得して投稿するだけ」の小さな仕組みです。でも、本番運用で本当に怖いのは、通知に失敗したのにメールだけ既読になることでした。
先に既読にすると取りこぼす
単純な実装では、次の順番になりがちです。
未読メールを取得
↓
既読に変更
↓
Discordへ送信
この順番でDiscord APIが一時的に失敗すると、メールは既読なのに通知は届きません。次回の実行では未読検索に出てこないため、そのまま取りこぼします。
そこで順番を逆にしました。
未読メールをUID単位で取得
↓
Discordへ送信
↓ 成功した場合だけ
メールを既読化
↓ 失敗した場合
未読のまま次回リトライ
スレッドではなくメッセージ単位で見る
Gmailでは、同じ件名のやり取りがスレッドにまとまります。
スレッド単位で未読判定すると、新しい1通を通知したいだけなのに、同じスレッド内の古いメールまで再送することがあります。
今回はIMAPのUIDを使い、メッセージ単位で処理しました。これにより、同じスレッドに返信が追加されても、新しく届いた未読だけを転送できます。
複数アカウントを1つの仕組みで扱う
運用では、アカウントごとに通知先や抽出条件が異なります。
そこでコードを複製するのではなく、「接続情報・差出人フィルター・Discordチャンネル」を設定として持たせました。アカウント追加時は設定を増やすだけです。
認証情報は.envへ分離し、Gmailには通常のパスワードではなくアプリパスワードを使用します。Discordのトークンもリポジトリへ入れません。
小さなBotほど失敗時の設計が効く
このBotで一番重要だったのは、華やかなAI機能ではありませんでした。
「どの時点で処理済みにするか」
「途中で落ちたら次回どう回復するか」
「同じ通知を二重送信しないか」
この3点です。
定期実行は正常系より、ネットワーク障害やAPIエラーが起きたときの動きを先に決めたほうが安定します。
自動化は、成功したときに動くことより、失敗しても情報を失わないことのほうが大事だと実感した案件でした。
