simフリー版ドコモメールの着信をIMAP4 IDLE→IFTTT→PushBullet でプッシュ通知
ドコモ回線で SIMフリー端末(Android)へ変更すると、ドコモメール(spモードメール)の着信が特殊SMSで通知されなくなる
simフリー端末用の公式ドコモメールアプリは、15分間隔でのポーリング受信
連絡は他のツールに移りつつあるため、あまり支障はないが、実験的メモです
注意
キャリア端末での着信通知は SMSで起動するため、Android端末が Doze 状態でも通知されますが、今回の方法は Androidのプッシュを最終的に利用しているため、Dozeの影響を受けます
着信トリガーで、SMSや電話着信を起動すれば、リアルタイム性を保つことは可能かと思います(今回はそこまで突っ込んでません)
試したけどNGだった事
- ドコモメール設定(spモード接続)から user-agentを iPhone へ変更して、着信お知らせメール(SMS)をオンにしてみる → 通常SMSが到着した形跡なし
- ドコモ公式端末から DcmWapPushHelper.apk と jp.nttdocomo.carriermail-2.apk を移植 → jp.nttdocomo.carriermail-2.apk(ドコモメール)は、起動と強制終了を繰り返して利用できず、DcmWapPushHelper.apk + ドコモメール(simフリー用)は、プッシュの反応なし
ということで、IMAP4 の IDLEを用いて、メール着信イベントを取得するしかないという事になりました
IMAP4 IDLE は早い話、セッションをつないだままにしてボックスに変化があったらサーバからクライアントへメッセージを送る --- という方法なため、端末アプリで IMAP4 IDLE を用いると、常にセッションを張り続ける→電池を消耗する という事は容易に想像されます。
今回は、常時起動したサーバ(今回は手持ちのVPS)で、IMAP4 IDLEを監視して、メール受信イベント → IFTTT WebHook → PushBullet で端末に「何か来たよ」の通知を行う事としました
メール受信イベント以下は、Gmailへ通知を送るなどでも同じです
※ imap.select('inbox') で受信フォルダを選択しています
それ以外のフォルダの通知を受ける場合、他のを指定する必要があります
日本語の場合 utf7でエンコード?(未確認)
Pyhotnソース(終了は ctrl + d) 同じ場所に log ディレクトリを作成してください
import datetime import imaplib import httplib2 import urllib import time import signal import os signal.signal(signal.SIGINT, signal.SIG_DFL) # ctrl + d # imap4へ接続して imapオブジェクトを返す(失敗は False) def connect_iamp_server(): imap_server = 'imap.spmode.ne.jp' imap_port = '993' imap_user = '******@docomo.ne.jp' imap_pass = '******' try: imap = imaplib.IMAP4_SSL(imap_server,imap_port) sock = imap.socket() # sock.settimeout(60 * 15) # NATタイマーにかかる場合タイムアウトを設定 imap.login(imap_user,imap_pass) except imaplib.IMAP4_SSL.error as e: print(e) return False else: return imap # Http GET or POST def httpExecute(url, user = '', passwd = '', postData = ''): for key in postData: if postData[key] == None: postData[key] = '' http = httplib2.Http(timeout=8) if user != '': http.add_credentials(user, passwd) if postData != '': try: content = http.request(url, method="POST", headers={'Content-type': 'application/x-www-form-urlencoded'}, body=urllib.parse.urlencode(postData) )[1] return content.decode() except httplib2.ServerNotFoundError: return '' else: try: (resp, content) = http.request(url, 'GET') return content.decode() except httplib2.ServerNotFoundError: return '' def printtime(s): now = datetime.datetime.now() writeLn = now.strftime("%Y-%m-%d %H:%M:%S ") + s print(writeLn) logFile = os.path.dirname(os.path.abspath(__file__)) + os.sep + "log" + os.sep + now.strftime("%Y%m%d") + ".log" with open(logFile, mode='a') as f: f.write(writeLn + '\n') def main(): while True: mailExists = False imap = connect_iamp_server() if imap != False: printtime('M: Connected IMAP4 Host') imap.select('inbox') imap_idletag = imap._new_tag() printtime('C: %s IDLE'%(imap_idletag.decode('utf-8'))) imap.send(b'%s IDLE\r\n'%(imap_idletag)) imap_line = imap.readline().strip().decode('utf-8') printtime('S: ' + imap_line) if imap_line == '+ .': try: while True: imap_line = imap.readline().strip().decode('utf-8') printtime('S: ' + imap_line) if imap_line.startswith('* BYE ') or (len(imap_line) == 0): mailExists = False break if imap_line.endswith('EXISTS'): mailExists = True printtime('C: DONE') imap.send(b'DONE\r\n') imap_line = imap.readline().strip().decode('utf-8') printtime('S: ' + imap_line) break # 上記以外のコマンドはループ(IMAP4を操作してもレスポンスが返ってくる) except: mailExists = False pass finally: # imap.close() # タイムアウト時にエラーが発生 imap.logout() printtime('M: Disconnect IMAP4 Host') if mailExists: printtime('M: mail Exists') # メール到着処理 postData = {'value1': 'ドコモメール'} httpresponse = httpExecute('https://maker.ifttt.com/trigger/*******/with/key/*******', '', '', postData) printtime('M: IFTTT > ' + httpresponse) else: # 接続NG -> 60秒待ち time.sleep(60) if __name__ == '__main__': main()
ドコモの仕様書どおり IDLE 30分で BYE切断になるが、NATタイマーがそれ以下の場合、タイムアウトを設定する(コメントアウトを外す)
コマンドラインでうまくいったら、pythonをデーモン化するメモ あたりでデーモンとして監視させればOK
参考文献
imap4libでpush通知と遊んでみる --- デーモン移行時、改行コードに注意
コメント