sesとlambdaでメールをslackに通知してみよう

27
SES と Lambda ととととと Slack と ととととととと 2016 と 3 と 21 と ととと

Upload: kenichirou-kimura

Post on 16-Apr-2017

2.625 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: SESとLambdaでメールをSlackに通知してみよう

SES と Lambda でメールを Slack に通知してみよう     

2016 年 3 月 21 日木村健一郎

Page 2: SESとLambdaでメールをSlackに通知してみよう

名前:木村健一郎所属:株式会社コム・アンド・コムお仕事:技術に関することはなんでも好きな言語: perl好きな DB : PostgreSQL

Page 3: SESとLambdaでメールをSlackに通知してみよう

今日のお題:  SES と Lambda でメールを Slack に通知してみよう

Page 4: SESとLambdaでメールをSlackに通知してみよう

Slack 使ってますか?

•チャットツールです•WEB ブラウザ、 iOS/Android/Windows/Mac アプリで使えます•API あります•詳しくは http://slack.com/  へ

Page 5: SESとLambdaでメールをSlackに通知してみよう

メール使ってますか?

•なんだかんだで使わざるを得ない重要なメールを携帯に飛ばすとかよくあるよね?

•監視システムからの通知もメールが基本最近は API 叩けたり、 slack プラグインがあることも

•できれば通知系は slack にまとめたいよね?

Page 6: SESとLambdaでメールをSlackに通知してみよう

メールの内容を slack に飛ばそう!

ぱっと思いつくレガシーなやり方

1.SMTP サーバを作る。例えば postfix 。2.受信するメールアドレスを作って、そこ宛のメールをコマンドに渡す3.コマンドにはメールが標準入力経由で渡されるので、頑張ってパースして slack に飛ばす

hoge: “ | /path/to/command”/etc/aliases  にこんな感じで書く

Page 7: SESとLambdaでメールをSlackに通知してみよう

・・・超めんどくさい (´ ・ ω ・ `)

( 特にサーバのお守りなんてしたくない )

Page 8: SESとLambdaでメールをSlackに通知してみよう

やっぱ時代はサーバレスでしょ! ( `・ ω ・ ´)

( 言ってみたかった )

Page 9: SESとLambdaでメールをSlackに通知してみよう

構成インターネット

SES

メール

S3S3 に保存

イベント通知

メール読み込み

API 呼び出し

Page 10: SESとLambdaでメールをSlackに通知してみよう

1. S3 を設定する

受信したメールを保存する S3 を設定します。適当な名前でバケット作りましょう。

( )S3※ オブジェクトは Lambda に渡すためにしか使わないから、期限を設定して自動で消しましょう!

Page 11: SESとLambdaでメールをSlackに通知してみよう

{"Version": "2008-10-17","Statement": [

{"Sid": "GiveSESPermissionToWriteEmail","Effect": "Allow","Principal": {

"Service": ["ses.amazonaws.com"

]},"Action": [

"s3:PutObjectAcl","s3:PutObject"

],"Resource": "arn:aws:s3:::BUCKET_NAME/*","Condition": {

"StringEquals": {"aws:Referer": "ACCOUNT_NO"

}}

}]

}

Policy はこんな感じで。

Page 12: SESとLambdaでメールをSlackに通知してみよう

2. SES を設定する

受信するドメインを決めます。自分で持ってるドメインでサブドメイン作るなり、新しいドメイン取るなりでまず準備しましょう。

手順1.メールアドレスを登録する2.ドメインの verifyをする (Route53なら早いです )3.アクションを追加するS3に保存するので、先ほどのバケット名を設定します

Page 13: SESとLambdaでメールをSlackに通知してみよう

今更ですが、なんで S3 ?

なんで S3 経由?アクションに Lambda ってあるやん?

S3 使わないと、本文や添付ファイルが取れないから

(多分理由は、 Lanbda 呼び出すときに渡すデータがでかいと嫌ってことかと思います)

Page 14: SESとLambdaでメールをSlackに通知してみよう

3. Lambda ファンクション書くぜ!

今回は Python で書きます。理由は以下の通り。

1.メールを取り扱うライブラリが標準である2.Slack 連携のライブラリがある3.新しく使えるようになったから試してみたい4.matetsu さんの記事を参考にしたから

Page 15: SESとLambdaでメールをSlackに通知してみよう

下準備

Python2.7 のインストールは適当に。ワークディレクトリを作って、 slack 用のライブラリをインストールします。

%mkdir ses-slack%cd ses-slack%pip install slackweb -t ./

Page 16: SESとLambdaでメールをSlackに通知してみよう

コード書くぜ(1)

lambda_function.py というファイルで作ります。utf-8 で書きます。

# coding: utf-8from __future__ import print_functionimport boto3import jsonimport ConfigParserimport emailfrom email.parser import FeedParserfrom email.header import decode_headerimport slackweb

出だしはこんな感じで。

Page 17: SESとLambdaでメールをSlackに通知してみよう

コード書くぜ(2)

ハンドラーの前半。 S3 からメールを取得。

def lambda_handler(event, context): try: record = event["Records"][0] bucket_region = record["awsRegion"] bucket_name = record["s3"]["bucket"]["name"] mail_object_key = record["s3"]["object"]["key"] s3 = boto3.client('s3', region_name=bucket_region) mail_object = s3.get_object(Bucket = bucket_name, Key = mail_object_key) mail_body = '' try: mail_body = mail_object["Body"].read().decode('utf-8') except: try: mail_body = mail_object["Body"].read().decode('iso-2022-jp') except: mail_body = mail_object["Body"].read()

  msg_object = email.message_from_string(mail_body)

Page 18: SESとLambdaでメールをSlackに通知してみよう

コード書くぜ(3)

ハンドラーの中盤。本文、サブジェクト、送信元を取得します。 if msg_object.is_multipart(): body = msg_object.get_payload()[0] else: body = msg_object try: body = body.get_payload(decode=True).decode(body.get_content_charset()) except: #iso-2022-jp なのに丸文字があるとき code = 'iso-2022-jp-2004' body = body.get_payload(decode=True).replace('\033$B', '\033$(Q').decode(code)

(d_sub, sub_charset) = decode_header(msg_object['Subject'])[0] if sub_charset == None: subject = d_sub else: subject = d_sub.decode(sub_charset) (d_from, from_charset) = decode_header(msg_object['From'])[0] if from_charset == None: mfrom = d_from else: mfrom = d_from.decode(from_charset)

Page 19: SESとLambdaでメールをSlackに通知してみよう

コード書くぜ( 4 )

ハンドラーの後半。エラーハンドリングします。 except:  subject = u"Error!"  body = u" メールを受信しましたが、エラーが発生しました。 " mfrom = u" 送信元不明 "

どうしてもおかしな形式のメールというのはあるものでして・・・

Page 20: SESとLambdaでメールをSlackに通知してみよう

コード書くぜ( 5 )

ハンドラーの終盤。いよいよ slack に流します。 inifile = ConfigParser.SafeConfigParser() inifile.read("./config.ini") attachments = []

attachment = { "fallback": u"From:%s\nSub:%s" % (mfrom,subject), "pretext": u“From:%s\nSub:%s" % (mfrom,subject), "color": "#aaaaaa", "text": body } attachments.append(attachment)

slack = slackweb.Slack(url=inifile.get('slack', 'hook_url')) slack.notify(attachments=attachments, channel=inifile.get('slack', 'channel'), username=inifile.get('slack', 'username'), icon_emoji=inifile.get('slack', 'icon_emoji'))

return "CONTINUE"

Page 21: SESとLambdaでメールをSlackに通知してみよう

コード書くぜ( 6 )

設定ファイルを config.ini という名前で準備します。[slack]hook_url = https://hooks.slack.com/services/***username = alert_botchannel = 流す先のチャンネル名icon_emoji = :guardsman:

hook_url は slack の設定から取得します。Web ブラウザでアクセスし、設定の「 Apps & Custom Integrations 」→「 Incoming WebHooks 」です。

Page 22: SESとLambdaでメールをSlackに通知してみよう

アップロードするよ!

zip でまとめます。%zip -r ses-s3-lambda-slack.zip config.ini lambda_function.py slackweb

で、これを管理コンソールからアップします

Page 23: SESとLambdaでメールをSlackに通知してみよう

S3 のイベント設定するよ!

先ほどの S3 バケットに更新イベントを追加します。Lambda の管理コンソールだけでなく、以下のように S3 の管理コンソールからも追加できます。

Page 24: SESとLambdaでメールをSlackに通知してみよう

先ほど設定したメールアドレスにメールを送ってみましょう。

動かないときは以下のようにちょっと修正してローカルで動かしてみる ( 引数にテキストファイルとして保存したメールを渡す ) とデバッグしやすいです。もしくは、 print すると CloudWatch のログに出力されるので print デバッグで。import sys

def lambda_handler(m): try: mail_object = email.message_from_string(m)

……

return "CONTINUE"

if __name__ == "__main__": if len(sys.argv)>1: raw=open(sys.argv[1]).read() else: print "no args" exit

lambda_handler(raw)

5 .試験するよ!

Page 25: SESとLambdaでメールをSlackに通知してみよう

6 .応用するよ!

ここまでできたら色々遊べますね。•キーワードをハイライトしたり色を変える•本文に応じて通知するメールを取捨選択する•Slack から返信もできるようにしてみる•添付ファイルも見れるようにしてみる•Twilio と連携して SMS も送ってみる

色々遊んでみましょう!

Page 26: SESとLambdaでメールをSlackに通知してみよう

7 .感想

• Lambda 超便利 (^o^)• SES はウィルスメールフィルタなどもあって便利• この組み合わせ、スロッティングとか考えなくていいし楽

ちん• もっと楽にデバッグできない?• Perl on Lambda マダー?

たぶん永久に来ない? (´ ・ ω ・ `)• Qiita にまとめてますのでコードはこちらを参考に

http://goo.gl/2m0dqK

Page 27: SESとLambdaでメールをSlackに通知してみよう