LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログ

SES + S3 + LambdaでGmailの添付ファイルを自動抽出する

バックエンド兼Androidアプリエンジニアの高橋です。

弊社のシステムの一部に、特定のメール(Gmail)を受信したタイミングで、その添付ファイルを使ってバッチ処理を行いたいという要件があります。

Gmailには受信トリガーを設定する事ができないので、GmailのAPIを定期的にポーリングする事で擬似的?に受信を検知したりする方法がありますが、今回はGmailのAPIをポーリングをせずにAWS上で実現する方法をご紹介したいと思います。

全体図

このような構成図となりました。

f:id:ktx_ku:20190719172516j:plain

一つずつ流れを説明していきます。

Gmail → SES

Gmailに来たメールをSESに転送します。

Gmailに受信トリガーが設定できないのであれば、転送先で受信トリガーを設定すればいいという考え方です。

全部のメールを転送すると大変なので、転送フィルターで必要なメールだけを転送するようにします。

転送先のドメインはRoute53でMXレコードを設定します。 f:id:ktx_ku:20190719172906p:plain

値は、画像にあるように「10 inbound-smtp.us-east-1.amazonaws.com」固定です。

SES → S3

次に、SESのコンソール画面でEmail Receiving のRuleSetを作成します。 f:id:ktx_ku:20190719161214p:plain

Recipentには先ほどRoute53に登録したドメインを入力します。(画像は適当です) f:id:ktx_ku:20190719161256p:plain

なお、この後ドメインの認証のためにTXTレコードが必要になりますが、

Route53を使っていると自動でRoute53に登録してくれるので、道なりに進めればOKです。

その次にSESで受信した時のActionを設定する画面に移ります。

ここでは、受信メールをS3に送ったりLambdaで処理したりする事ができますが、S3に送るようにします。

ここでLambdaに処理を渡してしまうとLambda側でメールの本文が見えないようです。

f:id:ktx_ku:20190719162304p:plain

Rulesetの設定が終わって、Status = EnabledになればOKです。

S3 ⇆ Lambda

最後にLambdaを作ります。

Lambdaの起動トリガーに、SESで設定したバケットの s3:ObjectCreated を設定します。

また、Lambdaでメールから抽出した添付ファイルをS3に戻すために、適切なIAM Roleをつけてあげる必要があります。

ここら辺の設定はServerless Frameworkを使うと楽です。

f:id:ktx_ku:20190719164559p:plain

作成するLambda関数はこんな感じです。

LambdaはRubyの例です。(サンプルなので動作保証しません。)

def upload_attachment(event:, context:)
  s3 = Aws::S3::Resource.new
  bucket_name = event["Records"][0]["s3"]["bucket"]["name"]
  key = CGI.unescape(event["Records"][0]["s3"]["object"]["key"])

  begin
    # emailをS3からダウンロード
    tmp_path = '/tmp/' + key
    s3.bucket(bucket_name)
      .object(key)
      .get(response_target: tmp_path)
    email = Mail.read(tmp_path)

    # 添付ファイルをS3にアップロード
    email.attachments.each do | attachment |
        filename = CGI.unescape(attachment.filename).downcase
        upload_bucket = s3.bucket(ENV['upload_bucket'])
        date = Date.today.strftime('%Y%m%d')
        upload_bucket.object("#{date}/#{filename}").put(body: attachment.decoded)
    end

  rescue Exception => e
    raise e
  end
end

動作確認

ここまでできたら、SESのRecipentに設定したドメインにメールを送ってみて、動作確認します。

添付ファイルがS3のバケットに上がれば目的達成です!

まとめ

今回は、AWSを使ってGmailの受信を検知する方法をご紹介しました。

全体的な流れしか説明していないので、実際に作業する際は他の記事も参照してやってみてください。

細かいところまで書こうとすると、1ページじゃとても書ききれませんでした。。。

Lambdaを作成するところ以外は短時間で構築できると思います。

最後に、弊社LCLではこのようなAWSを活用した仕組みづくりを日々作り続けています。

いろんなアイデアを受け入れたいと思うので、力を貸していただける方を絶賛募集中です!

www.lclco.com