さび付いてた技術を掘り起こすために自由研究な体で作ってみました!
■やってみたこと APIGatewayとlambda(python2.7)を組み合わせて、URLに渡したパラメータをもとにメッセージを変更して勤怠連絡メールを送る
以下、内容です。
・以前の会社でソースを構築してシステムを作ることが減っていたため、レコチョクで再勉強しよう!という背景があった。 ・勉強するにあたり最新のトレンドやメジャー言語を選択。(pythonを選択) ・サーバ環境はAWSを組み入れて触りながら理解を深める。(出来れば自前アカウントのため節約、サーバレスで構成) ・APIの理解を深めたいため、Google検索でHitした東京メトロの公開API(要登録制)を 用いて列車の遅延状況もメール本文に組み込む
(作成理由) そもそも通勤利用している千代田線はラッシュ時に遅延が多く、運転見合わせの際はホームに上がれないほどの 混雑のため、ワンタッチでメールを送りたい。遅延情報が一緒についてたらCool。 どうせなら、遅刻、休暇もパラメータを切り替えて内容を変えて送りたい。
(概要) 下記概要図に示す通り、携帯またはPCからパラメータを埋め込んでアクセスした APIGatewayを通してlambda側でパラメータ値を判定してメッセージを組み換えGoogleメールを送信する。
(パラメータ) in 0:列車遅延状況の東京メトロAPI呼び出し確認用 1:列車遅延の為、遅れての出勤連絡 2:体調不良による、遅れての出勤連絡 3:体調不良による、AM休連絡 4:体調不良による、全休連絡 5:テスト用メール送信 out 実行したパラメータ番号
クライアントアプリ側はURLのアイコン化ツールで作成しました。
(メール) メールの送信はSMS機能を用いて送信した場合、受信者の承諾が必要なこと AWSからの送信でアラートとの見分けがつかないためGmailを用いた。 ただしtcp:25は迷惑メール対策で閉じられているためsubmission port:587を使用
<はまったところ> 1.最新の観点でpython3.5を選択したが、lambdaがpython2.7のため関数の変更が必要だったこと 2.lambdaに引数を渡すところで、 def lambda_handler(event, context): 以下略)で変数を取り込んで処理していくが、 ハンドラーの外に変数を簡単に渡せると思っていたが内部完結が必要であった。 パラメータの扱いにeclipse上ではlibのsys関数を用いて変数を組んでいたためlambdaでは混乱した。 3.Gmail側の不正アクセス監視が働いており、AWS初回のアクセスは未知の端末としてアクセスがはじかれる。既存端末から心当たりのあるアクセスとして有効にする(AWS側で端末が変更されると都度承認が必要)
<今後の課題> outメッセージの強化 APIGatewayにAPIキーの設定 路線、宛先、名前の変数化など
(参考した代表サイト) http://qiita.com/yuyakato/items/89fcef9746afbf48977a http://qiita.com/seiketkm@github/items/c91d8a62af9883dd00d6 https://developer.tokyometroapp.jp/info
#coding: UTF-8
'''
Created on 2016/07/08
@author: s-nonomiya
'''
import urllib
import json
from encodings.utf_8 import decode
def lambda_handler(event, context):
#print("Received event: " + json.dumps(event, indent=2))
print("value1 = " + event['key1'])
print(event['key1']) # Echo back the first key value
# 引数チェック
if (len(event['key1']) != 1): # 引数が足りない場合は、その旨を表示
print("Usage: # 引数不足" + str(event['key1']) )
quit() # プログラムの終了#
if (str(event['key1']) < "0" or str(event['key1']) > "5"): # 引数値が不正場合は、その旨を表示
print("Usage: # 引数値エラー" + str(event['key1']) )
quit() # プログラムの終了
#raise Exception('Something went wrong')
#ToykoMetroAPI
TAPI_ENDPOINT = '東京メトロから付与されたエンドポイント'
DATAPOINTS_URL = TAPI_ENDPOINT + "datapoints"
RDP = 'データ参照タイプ' #東京メトロアプリ開発者用公式サイトをご覧ください
RLINE = '発路線パラメータ' #東京メトロアプリ開発者用公式サイトをご覧ください
PASSLINE = '路線パラメータ' #東京メトロアプリ開発者用公式サイトをご覧ください
COMSUMERKEY = 'コンシューマキー' #東京メトロアプリ開発者用公式サイトをご覧ください
import smtplib
from email.mime.text import MIMEText
import datetime
#API固定token
TOKEN_KEY= '東京メトロから付与されたtoken'
#路線名称辞書 パラメータ値は東京メトロアプリ開発者用公式サイトをご覧ください
linename = { "銀座線のパラメータ":"東京メトロ銀座線",
"丸ノ内線のパラメータ":"東京メトロ丸ノ内線",
"日比谷線のパラメータ":"東京メトロ日比谷線",
"東西線のパラメータ":"東京メトロ東西線",
"千代田線のパラメータ":"東京メトロ千代田線",
"有楽町線のパラメータ":"東京メトロ有楽町線",
"半蔵門線のパラメータ":"東京メトロ半蔵門線",
"南北線のパラメータ":"東京メトロ南北線",
"副都心線のパラメータ":"東京メトロ副都心線"
}
#URL生成
CALL_URL = DATAPOINTS_URL + RDP + RLINE + PASSLINE + COMSUMERKEY + TOKEN_KEY
response = urllib.urlopen(CALL_URL)
content = json.loads(response.read().decode('UTF-8'))
#Jsonからのデータ要素取得
tmpdate = content[0]["配信日"] #東京メトロアプリ開発者用公式サイトをご覧ください
pname = content[0]["路線パラメータ"] #東京メトロアプリ開発者用公式サイトをご覧ください
opstatus = content[0]["運行状況のテキスト"] #東京メトロアプリ開発者用公式サイトをご覧ください
#日付表示形式の加工
tmpdate2 = tmpdate.replace("T"," ")
tmpdate3 = tmpdate2.replace("-","/")
gdate = tmpdate3[0:19]
linenm = linename[pname]
print(linenm) #対象路線
print(opstatus) #運転状況
print(gdate) #現況時刻
today = ''
today = datetime.date.today()
#UTC+8h加算
today = today + datetime.timedelta(hours=9)
p_today = today.strftime("%Y/%m/%d ")
gdate2 = gdate.encode('utf-8')
opstatus2 = opstatus.encode('utf-8')
#メール本文辞書
sentence = { "1":"列車遅延のため、遅れての出社となります。\n"\
+"緊急の用件があれば携帯まで連絡お願いいたします。\n"\
+ "\n" + linenm +" " + gdate2
+ "\n"
+ opstatus2 +"\n"\
+ " Info from Tokyo metro App\n",
"2":"本日体調不良のため、遅れて出社致します。\n"\
+"緊急の用件があれば携帯まで連絡お願いいたします。\n"\
+"ご面倒おかけして申し訳ありません。\n",
"3":"本日体調不良のため、様子見て午後から出社いたします。\n"\
+"緊急の用件があれば携帯まで連絡お願いいたします。\n"\
+"ご面倒おかけして申し訳ありません。\n",
"4":"本日体調不良のため、急で申し訳ありませんが全休いたします。\n"\
+"緊急の用件があれば携帯まで連絡お願いいたします。\n"\
+"ご面倒おかけして申し訳ありません。\n",
"5":"<TEST>メール疎通、テスト送信\n"\
+ "\n" + linenm +" " + gdate2
+ "\n"
+ opstatus2 +"\n",
"0":""
}
if (str(event['key1'])=="1" and opstatus == "現在、平常どおり運転しています。"):
print("正常運行の為、メール送信処理を停止しました")
quit()
elif str(event['key1'])=="0" :
print("遅延状況表示:0")
else:
# 以下の内容を変更する
# me : 送信元アドレス, to_address : 送信先のアドレス,hostml :返信先アドレス, passwd : 送信元メールアカウントのパスワード
me = "送信元アドレス"
passwd = "送信元メールアカウントのパスワード"
hostml = "返信先アドレス"
if (str(event['key1'])=="5"):
to_address = ['疎通確認用アドレス' ]
else:
to_address = ['送付先メールアドレス1','送付先メールアドレス2','送付先メールアドレス3','送付先メールアドレス4' ]
titletext = "■勤怠連絡" + p_today + "ご自身のお名前"
body = "おはようございます。ご自身のお名前。\n"\
+ sentence[str(event['key1'])]\
+ "\n"\
+ " ※本メールの返信は以下メールにお願いいたします\n"\
+ hostml +"\n"\
+ "\n"\
+"以上、よろしくお願いいたします。"
message = MIMEText(body)
message['Subject'] = titletext
message['From'] = hostml
message['To'] = ', '.join(to_address)
#ここでサブミッションポートを使ってメール配信処理を組み込む
# Send the message via our own SMTP server.
s = smtplib.SMTP('smtp.gmail.com',587)
s.ehlo()
s.starttls()
s.login(me, passwd)
#s.message(message)
s.sendmail(
me,
to_address,
message.as_string(),
)
s.close()
print("メッセージ内容:" + sentence[str(event['key1'])])
#print("メール送信処理が完了しました")
#nkey = len(event['key1']) # 引数の個数
return str(event['key1'])
野々宮聡
今年の半ばからレコチョクエンジニアとして働き始めた野々宮 SATEOSHI(写真:スペルミス?)です。
斬新なサービスやその成り立ちに興味あります。
このサイトでは色々な興味あること、気になることや自分の経験・体験を書いていきたいと思います。