AWS LambdaでRubyライブラリを使って添付ファイルを送信する

AWS Lambdaでは多くのプログラミング言語が使えますが、その中にRubyもあります。バージョンは執筆時点(2020年08月)で2.7となっており、最新に対応しています。もちろんこのRubyとCustomers Mail CloudのRubyライブラリを組み合わせてメール送信も可能です。

今回はS3にファイルをアップロードされたのをトリガーにして、そのファイルをメールする仕組みを作ってみます。

ローカルのコードを整備

AWS LambdaではRubygemsでインストールしたライブラリも利用できますが、あらかじめZipなどにまとまっていなければなりません。そのため、まず作業用のフォルダを作成します。

mkdir lambda_ruby
cd $_

次に .bundle フォルダを作成し、その中にconfigファイルを作ります。内容は次の通りです。

---
BUNDLE_PATH: "vendor/bundle"

そして Gemfileを作成します。内容は次の通りです。

source 'https://rubygems.org'

gem 'aws-sdk-s3'
gem 'customers_mail_cloud'
gem 'multipart-post'
gem 'mime-types'

後はライブラリをインストールします。

bundle

AWS Lambdaでの準備

AWS Lambdaで関数を作成したら、まず環境変数を作成します。今回は次の通りです。APIユーザ名、APIキーについては Microsoft Azure で手軽にメール送信する - Customers Mail Cloud ブログ を参考に取得してください。

キー
API_USER Customers Mail Cloudで作成するAPIユーザ名です
API_KEY Customers Mail Cloudで作成するAPIキーです
FROM_ADDRESS メール送信元のアドレスです
FROM_NAME メール送信元の名前です

アクセス権限

関数のロールに対してS3のアクセス権限(今回は読み取り権限のみ)を設定します。

実行可能時間

ダウンロードするファイルサイズにもよりますが、標準の5秒では処理がまず終了しません。今回は20秒としています。

コードについて

コードは def lambda_handler(event:, context:) の中に記述していきます。ファイル名は lambda_function.rb です。

ライブラリの読み込み

S3のライブラリと、Customers Mail Cloudライブラリを読み込みます。これは関数より前に記述します。

require 'aws-sdk'
require 'customers_mail_cloud'

S3の初期化

S3を初期化します。リージョンは自分が使うもの、かつLambdaと同じリージョンにしてください。

s3 = Aws::S3::Resource.new(region: 'us-east-1')

アップロードされてきたオブジェクトを特定する

オブジェクトに関する情報は event 変数の中に入っています。次のようにしてオブジェクトを特定できます。

record = event["Records"][0]['s3']
obj = s3.bucket(record["bucket"]["name"]).object(record["object"]["key"])

ファイルをダウンロードする

S3のファイルを /tmp 以下にダウンロードします。階層構造の場合もあるので File.basename を使っています。

file_path = "/tmp/#{File.basename(record["object"]["key"])}"
obj.download_file(file_path)

Customers Mail Cloudを準備する

まず初期化します。環境変数に設定したAPIキーを使って初期化しています。

client = CustomersMailCloud::Client.new(ENV['API_USER'], ENV['API_KEY'])

Web APIのエンドポイントは契約ごとに異なります。それを指定します。

client.trial() # トライアルの場合
client.standard() # スタンダードの場合
client.pro(subdomain) # プロの場合。サブドメイン指定が必須です

後はメール送信に必要な宛先、送信元、件名、本文をそれぞれ指定します。FROMについては環境変数を使っています。

client.from = CustomersMailCloud::MailAddress.new(ENV['FROM_ADDRESS'], ENV['FROM_NAME'])
client.to << CustomersMailCloud::MailAddress.new('test@smtps.jp', 'Tester')
client.subject = 'We got a file'
client.text = 'S3に新しいファイルが追加されました'

添付ファイルを追加する

添付ファイルは attachments にファイルを追加します。ファイルのパスまたはファイルオブジェクトで指定できます。今回はパスで指定しています。

client.attachments << file_path

後はメール送信用のメソッドであるsendを実行すればOKです。

begin
  json = client.send
  puts json
rescue => e
  puts e
end

実行結果として、今回は14秒かかっています。

14558.70 ms

f:id:moongift:20200823154720p:plain
メールの受信例

全体のコードです。実装時の参考にしてください。

require 'json'
require 'aws-sdk'
require 'customers_mail_cloud'

def lambda_handler(event:, context:)
  s3 = Aws::S3::Resource.new(region: 'us-east-1')
  record = event["Records"][0]['s3']
  obj = s3.bucket(record["bucket"]["name"]).object(record["object"]["key"])
  file_path = "/tmp/#{File.basename(record["object"]["key"])}"
  obj.download_file(file_path)
  client.trial
  client = CustomersMailCloud::Client.new(ENV['API_USER'], ENV['API_KEY'])
  client.from = CustomersMailCloud::MailAddress.new(ENV['FROM_ADDRESS'], ENV['FROM_NAME'])
  client.to << CustomersMailCloud::MailAddress.new('test@smtps.jp', 'Tester')
  client.subject = 'We got a file'
  client.text = 'S3に新しいファイルが追加されました'
  client.attachments << file_path
  begin
    res = client.send
    { statusCode: 200, body: JSON.generate(res) }
  rescue => e
    { statusCode: 503, body: e.message }
  end
end

まとめ

AWS SDKは非常に大きく、すべてインストールしてしまうと10MBを超えてしまい、オンラインでは編集できなくなります。S3だけインストールするのがお勧めです。

今回の実装でAWS Lambdaを使ったメール送信処理がとても簡単にできるのが分かってもらえるかと思います。ぜひAWSを使ったシステム構築でもCustomers Mail Cloudを役立ててください。

クラウドからのメール送信を簡単に。確実に。| Customers Mail Cloud