will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

【Ver. 2】 AppStore Connectでアプリがレビューに入ったとか、リジェクトされたとかをSlackに通知する

adventar.org

この記事はCyberAgent Developers Advent Calendar 2018の12/14の記事です。

 

今回はタイトルの通り、AppStore Connectのステータスを通知する仕組みを実装していきます。

TR;DR

Amason AWSを使いました。 AppStore Connect -> SES -> SNS -> Lambda -> Slack

  1. Appleのメールの通知先にSESで受け取れるメールアドレスを追加する
  2. SESでメールを受ける
  3. SNSでメールの通知を受け取る
  4. Lambdaでメールをパースし、Slackに投げる

Lambdaではこちらのスクリプトを動かしました。

AWSLambdaAppStoreConnectStatus.py · GitHub

発端

このスクリプトをTypeScriptにバージョンアップしよう画策していました。そこで、会社の後輩が「AWSのLambdaでやってみては?」とアドバイスをくれたのでやってみました。

AWSはほぼ触れたことがなかったのでちょうどよかったです。各サービスの設定を説明していきたいと思います。普段はiOSエンジニアでAWSではEC2のmicroインスタンスを作ったことしかないマンなので予防線をひかせてください(笑)

blog.matsuokah.jp

元のスクリプトでやっていたこと

簡単に説明すると、こんなことをやっていました

  1. Google App ScriptでAppStore Connectからの未読のステータスメールを検索
  2. 件名含まれている文字列からステータスを判定
  3. Slackに通知する
  4. メールを既読にする

これを5分くらいのタイムスケジューラで動かしていました。

Pros
  • 無料
  • ほぼセットアップなしにできる
  • スプレッドシートに保存したりできるので、使い方は無限大
Cons
  • 既読にすると通知されない。
  • たまにスクリプトがこける。
  • 個人のアカウントでスケジューラを動かすため、引き継ぎが面倒
  • 若干のタイムラグがある

ということで、AWSを使っている組織であればメールの設定とAWSの設定をした方が、会社の資産としても使いやすいのは言うまでもないですね。それでは実際の作業ログを書いていきます

 

1. SESでメールを受け取ってLambdaを起動するところまで作る

1. SESのEmail受信設定を入れる

docs.aws.amazon.com

まずはマニュアル通り設定することで、メールを受け取ることができるようになります。今回はS3にメールを保存する必要はないのでスキップします。

また、ドメイン販売業者のDNSなどを利用している場合は、そちらのコンソールで作業が必要になります。自分は必要でMXレコードとTXTを外部のDNS設定で行いました。

2. Amazon SNSのトピックを作成する

適当に名前をつけて作ればOKです 

3. SESのActionでSNSのトピックにパブリッシュする

SESのコンソールで、先ほど作ったトピックにメールをパプリッシュする設定をいれます。Rule Setsから新たにルールを設定し、Actionを追加します。Actionの先でSNSを選択すると候補にトピックが出てくるので選択するだけです。エンコーディングUTF-8を選択しました

4. AWS Lambdaのエンドポイントを作成する

「一から作成する」で作っていけば終わります。今は作るところまででOKです

5. SNSサブスクリプションを作成する

SESと紐づけたトピックをサブスクライブし、Lamdaを起動するサブスクリプションを作成します。ここでもLambdが候補に出てきてくれるので、ぽちぽちしていけば終わります。

 

これで、メールを受け取って、Lambdaの関数を起動することができるようになりました。

 

SNSはトピックを入り口としてサブスクリプションがトピックと出口をつなぐようなものと捉えたらOKでしょうか。Apach FlumeのSource / Sinkのようなものをだなーと感じました

2. メールの内容を取得し、ステータスを検知する

これが地味にめんどくさかったです。

Lambdaでは第1引数のeventにトリガーとなった情報が入ってきます。

Lambdaのテスト設定にSESのメールオブジェクトがあったので、その通りにパースしてみたのですがうまくいきませんでした

一旦、EventのオブジェクトをS3にダンプして、JSONの中身をjqでみてみることにしました。

 

Python(boto3)でS3にデータをファイル保存せず直接アップロードする方法 | DevelopersIO

 

S3の権限設定にハマる

書き込もうとするとAccess Denidedと怒られました...

そこでLambdaを作成する時に一緒に作成されていた「ロール」に対しS3のWrite権限を設定することで、解決しました。

 

S3に吐き出されたJSONファイルを見てみると

events[0]['Sns']['Message']のなかにメールの件名が含まれている時JSONがあることがわかりました。

最終的に件名は 

json.loads(event['Records'][0]["Sns"]["Message"])["mail"]["commonHeaders"]["subject"]

で取得することができました。

 

あとは、件名からステータスを判定し、Attachmentを作ってWebHook URLを叩くだけです。

3. Slackに通知する

Pythonのrequestsを使ってURLを叩くのですが、pipでインストールしたライブラリをLambda上で使うにはベンダリング(依存関係を含め全てパッケージに含めること)をする必要があります。

 

こちらを参考にrequestsを含めたあとzipしてアップロードすることで解決しました

qiita.com

 

あとは元のスクリプトで組み込んだロジックを組み込めば終わりです!

 

ということでメールを送ってみます。

f:id:matsuokah:20181214151001p:plain

 

f:id:matsuokah:20181214151017p:plain

 

やたーーーー!

 

ということで、AppStore Connect -> SES -> SNS -> Lambda -> Slackでメールが来るようになりました。今日の午前2時くらいからやりはじめた初心者でもサクッとこういうことができるAWSはすごいですね(小並感)

料金は、Appleからのメールは多くても月に100件も行かないので無料枠の範囲内におさまりそうです。

 

本来ならterraformとかで自動的に構築するのがモダンなのでしょうか?

優秀な後輩たちに聞いてみようと思います。

 

ということで、こんな提案をしてくれる後輩たちがいる僕たちのチームで一緒に働きませんか!という広告を掲載して締めたいと思います。

www.wantedly.com

 

www.wantedly.com

 

まとめ

  • GASは便利だが属人化しがちという短所を持ち合わせているので、資産とするならAWSへの移行を視野に入れよう!
  • バックエンド/SREエンジニア応募よろしくです 🙏