SendGrid Receiver on AWS
SendGrid の Incoming Webhook 経由でメールを受け取るシステムをサーバーレスアーキテクチャで作りました。
目的
- 簡易なメール受信機
- 削除されてもいいやつを受ける
- もしくは待避機能をつける
- 通知はslack
- 詳細の閲覧は html
- 送信・返信・転送は特にしない
- どうしてもしたければ 別のメーラー からでも送信元いじって送ればいい
採用した技術・ツール
- SendGrid Incoming Webhook
- Amazon API Gatewawy
- AWS Lambda
- AWS Lambda@Edge (optional)
- Amazon S3 bucket
- Amazon CloudFront
- slack
- serverless framework
詳細
ノウハウなど
成果物
github で公開: https://github.com/take4mats/sendgrid-receiver-aws
構成
- SendGrid Incoming Webhook
- SendGrid can POST received email to specified API
- Amazon API Gatewawy
- AWS Lambda
- Amazon S3 bucket (email objects converted to html)
- Amazon CloudFront
- optional: Lambda@Edge で認証など
Tips
実際の構築を経てハマったこと、工夫したところ
multipart/form-data のパース
メールの Content-Type は multipart/form-data
となっており、 boundary の記号で本文を区切ってパースしないといけない独特な形式なので、加工には手間がいりそう。
頑張ってライブラリを探したらちゃんと先人が作ってくれていて、どうやらちゃんと扱えそうだ。
- multipart/form-data のパースをするには、
cgi
ライブラリのFieldStorage
クラスを使うと良いらしい。
sls deploy 時に必要な外部ライブラリも一緒にデプロイ
Lambda のランタイムを python 3.6 にすることはあっても、外部ライブラリをあれこれ入れるのは始めてだったので、うまく serverless framework で管理してやりたいということで、初チャレンジだった。
まず、 npm モジュール
serverless-python-requirements
をインストールするnpm install --save serverless-python-requirements
続いて、
serverless.yml
に追記.plugins
とcustom
のところに書きます。plugins: # ... - serverless-python-requirements # allow pip # ... custom: # ... pythonRequirements: dockerizePip: true # ...
S3 に置いた html ファイルの content-type がおかしい
どうも index.html ファイルへのリンクを押すとブラウザからダウンロードされてしまっておかしいなぁと思ったら、 Content-Type: binary/octet-stream
となっていた!(確認方法: S3 bucket で対象ファイルのメタデータを見る or curl 等でダウンロードしたときの html ヘッダを見る)
参考: S3に置いたhtmlファイルがブラウザダウンロードされてしまう時
Todo
2019/06/15時点でとりあえず簡潔に html でためて slack 通知もして、は動くようになったが、他にも色々
- 一覧ページを静的 html+js+css くらいで作成 (vue.js 勉強がてら?)
- 場合によってはデータベース使って管理(一覧化のためにメタデータのみか、重厚にメッセージ本体もか)
- 削除をしやすく
- 閲覧中に削除
- 一覧から選んで削除
- 場合によっては古いものは自動で削除
- 認証の見直し?
その他
(ボツ) Linux サーバでチュートリアル
SendGrid 公式のチュートリアルで Incoming Webhook に馴染んでおこう、ということで一番最初に試してみた構成。 Incoming Webhook を受けられる デモアプリを使って受信し、 slack にメールを転送するところまで。
- 参考
- SendGrid チュートリアル - メールを受信する
- POSTを受信するサンプルアプリケーション を使う
- Webhookのデバッグ で ngrok など学ぶ
やったこと
- slack
- webhook の token 取得しておく
- sendgrid-inbox
- git clone (sendgrid-demobox)
- rename it to
sendgrid-inbox
- Gemfile 編集, slack-incoming-webhook を追加など
- bundle install –path=.bundle
- src/slack.rb 作成
- .env に色々書く. domain, user/passwd, slack webhook
- bundle exec rackup
- development
- install ngrok (see my github account for more details)
- run ngrok:
ngrok http 9292
- http://xxxxxxx.ngrok.io -> localhost:9292 のトンネルが出来上がる
- SendGrid の webコンソールから incoming webhookの登録
- test.georgeorge.com –> https://id:pw@xxxxxxx.ngrok.io/receive
- ドメイン管理
- test.georgeorge.com の MX レコードを追加
- コレで動く!
- 色々動作確認していじったら、 git commit, git push -> 自分のrepository へ
- production
- アプリ
- repository から git clone
- bundle install
- rackup -p 9292 -h 0.0.0.0
- SendGrid の webコンソールから incoming webhookの登録
- georgeorge.com –> https://id:pw@おれのさば:9292/receive
- ドメイン管理
- georgeorge.com の MX レコードを追加
- コレで動く!
- アプリ