gmailに来た特定のメール通知をslackに投げてみた

令和になりました。もう1週間たっていますが。
GWは半分くらい研究所で、元号が変わってからは名古屋にいってきました。
名古屋といえば大須の電子部品屋ですが、今回は行っていません。


研究所での実験中、カウントレートやらモータの回転速度をリアルタイムで監視していて
異常値があったらインターロックをかけて実験を中断し、アラートメールが送信されるようにしています。

パソコンをつけているときはメールがすぐに確認できてよいのですが
寝ている時に問題が発生した場合に迅速に対応するため、指定したアラートメールが来た時のみ スマホに何かしらのポップアップ通知を出してくれたらいいのになあと感じていました。

てことでさくっとプログラムを書いてみました。
流れとしては
・アラートメールがきたら指定したラベルの受信boxに格納
・指定した時間毎に受信boxを確認しにいく
・新着メール(未読メール)があったら、件名をslackに投稿
といった感じです。


参考にしたサイト

qiita.com

tmegane.hatenablog.com

下のはセルフリファレンス。


Pythonコード

import imaplib
import email
import slackweb
import signal
import time

UserName = "mail@gmail.com" ##gmailのメールアドレス
PassName = "Pass"     ##gmailのアプリパスワード

gmail = imaplib.IMAP4_SSL("imap.gmail.com", '993')
gmail.login(UserName, PassName)
gmail.select("INBOX") #box選択
gmail.select("Alarm") #ラベル

global title


def ParAla(arg1,arg2):

    head, [data] = gmail.search(None, '(UNSEEN)') 
   ## ALLでSearchすると指定したラベルの全てのメールを読み込む
   ##UNSEENで未読メールのみ

    for num in data.split():
        ### 各メールへの処理 ###
        result, d = gmail.fetch(num, "(RFC822)")
        raw_email = d[0][1]
        #文字コード取得用
        msg = email.message_from_string(raw_email.decode('utf-8'))
        msg_encoding = email.header.decode_header(msg.get('Subject'))[0][1] or 'iso-2022-jp'
        #パースして解析準備
        msg2 = email.message_from_string(raw_email.decode(msg_encoding))
        subject = email.header.decode_header(msg2.get('Subject'))
        print(subject)
        title = ""
        for sub in subject:
            if isinstance(sub[0],bytes):
                title += sub[0].decode(msg_encoding)
            else:
                title += sub[0]

        print(title)

        ToSlack = slackweb.Slack(url=" 送信したいslackのURL ")
        ToSlack.notify(text=title)


signal.signal(signal.SIGALRM, ParAla)
signal.setitimer(signal.ITIMER_REAL, 5, 5) ## (signal.ITIMER_REAL,x,y)で1回目をx秒後に呼び出し、その後はy秒間隔で呼び出す

while True:
    time.sleep(1)

解説

imaplibgmailにログインし、メールボックス内からAlarmラベルのついた未読メールをがあったら中身をパースしてきています。
パースした情報のうち、タイトル部分を拾ってきて、指定したslackのチャンネルに投げるといった流れです。
また、ParAla関数を一定時間ごとに呼び出すために、signalモジュールを使っています。

signal.signal(signal.SIGALRM, ParAla)
signal.settimer(signal.ITIMER_REAL,x,y)

と入力することで、ParAla関数をプログラム起動から初回はx秒後に、その後はy秒間隔で繰り返し実行させています。

あとはこのpythonプログラムをraspberryPiあたりにいれて、実験中は常時起動させておけば
トラブルが発生したらいつでもslackで呼び出してくれます。いいんだか悪いんだか・・・・。