はじめに
推しのファンクラブ プラットフォームが変更され、これまでスマホアプリで受け取れていた ライブ配信開始通知が「メールのみ」 になった。
メールでも情報は届く。
ただ…
- プッシュ通知ほど即時性がない
- 他の通知に埋もれやすい
- 見逃したら致命的
という問題があった。
「じゃあ、自分で作るか。」
こうして作ったのが、通知メールをトリガーに、LINEへ即時通知する小さな仕組みだ。
やりたかったこと
やりたかったことは、とてもシンプル。
- 特定の通知メールを受信したら
- 条件判定して
- LINEに通知する
ただし、以下を前提条件とした。
- 非営利・個人利用
- クローズド運用
- 低コスト
- 24時間安定稼働
「派手さよりも、壊れにくさ」を最優先にしている。
全体構成(設計の全体像)
[ファンクラブ通知メール]
↓
[IMAPメールボックス]
↓
[Raspberry Pi]
- Python
- 未読メール監視
- 件名 / 差出人判定
↓
[LINE Messaging API]
↓
[LINE通知]
※ Raspberry Pi は「通知専用」として単機能で運用している
Webhookや公式APIは使っていない。
メールという、最も枯れていて安定したインターフェイスを入口にした。
技術スタック
- Raspberry Pi(常時稼働)
- Debian系OS
- Python 3
- imaplib / email
- LINE Messaging API(通知の出口)
- cron(1分間隔)
- logrotate
- GitHub(ソース管理)
設計思想(インフラ視点)
なぜ公式APIを使わなかったか
- APIが提供されていない
- 仕様変更リスクが読めない
- 個人用途にはオーバースペック
メールは仕様変更されにくく、最後まで残り続けるインターフェイス だと判断した。
なぜ cron + IMAP にしたか
IMAP IDLE も検討したが…
- 常時接続の管理が必要
- プロバイダ側制限の可能性
- 落ちたときの復旧がやや面倒
といった理由から、今回は採用しなかった。
cron で 1分ごとに未読メールを確認 する方式は、正直かなり地味だが、インフラ的にはこういうのが一番強い。
派手なことは何もしていない。
その代わり、壊れにくい。
多少の遅延よりも、「静かに、確実に動き続けること」 を重視した。
実装の要点(抜粋)
未読メールの検知
未読メールの取得は以下のようにしている。
typ, data = M.search(None, "UNSEEN")
取得したメールに対して、
- 差出人(From)
- 件名(Subject)
を部分一致で判定し、条件に合致した場合のみ通知を行う。
二重通知を防ぐ仕組み
通知後は、そのメールを既読化する。
M.store(msgid, "+FLAGS", "\\Seen")
これにより、
- cron が毎分回っても
- 同じ通知が再送されない
という冪等性を担保している。
LINE通知(通知の出口)
LINE Messaging API は 通知の出口としてのみ使用している。
- クローズドグループで運用
- 無料枠で検証
詳細なAPI解説は本題ではないため割愛する。
運用して見えてきたポイント
実装よりも、むしろ運用で学びが多かった。
- cron 実行時は 環境変数が引き継がれない
- ログには 必ずタイムスタンプを付ける
- logrotate を入れないとログが肥大化する
- secrets(トークン・メール情報)は GitHub に絶対上げない
そのため
- .env は Git 管理外
- GitHub には example ファイルのみ配置
という構成にした。
実際に使ってみて
初めて通知が鳴った瞬間、正直ちょっとニヤッとした。
インフラ屋にとって、いちばんテンションが上がる瞬間である。
派手な仕組みもUIもない。
ただ、ちゃんと「欲しいときに鳴る」。
インフラらしく、静かに仕事をする仕組み ができたと思っている。
ソースコード
秘密情報を含まない形で GitHub に公開している。
おわりに
この仕組みは地味だが
- APIに依存しない
- 個人でも運用できる
- 壊れにくい
という点で、個人的にはかなり気に入っている。
推し活とインフラは、意外と相性がいい。
静かに動き続けているときほど、価値がある。
