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通知と遊んでみる --- デーモン移行時、改行コードに注意
コメント