Lambda・SESを使って、添付ファイル付きメールを送信する

AWS運用自動化サービス「Cloud Automator」

渡辺です。
S3バケットにあるファイルをメールで毎月1回送信すべしというお仕事が発生しました。
パッと思いついた実装方法は以下となります。

  1. CloudWatch Events ルールのスケジュール式 で毎月1回Lambda Function を動かす。
  2. Lambda Functionの実装
    1. S3バケットにある指定ファイルを取得する。
    2. SESのメールで添付ファイルとして送信する。

CloudWatch Eventsの部分は特に問題なかったのですが、LambdaでS3から添付ファイル付きメールをSESで送信するという部分で少しコツがいることがわかりました。

SES

まず、SESの部分です。
AWSのドキュメントにサンプルコードがあるので、それを利用しました。
毎度おなじみのPythonとboto3での実装例が載っています。

  1. AWS SDK for Python (Boto) を使用して E メールを送信する
  2. AWS SDKs を使用して raw E メールを送信する

サンプルコードは上記の通り、2つありました。
1の方はsend_email()メソッドを使ったサンプル、2の方はsend_raw_email()メソッドを使ったサンプルとなっています。
添付ファイルをつけるには、send_raw_email()を使う必要があるようなので、2のサンプルコードを元にして開発してみました。

その前にsend_raw_email()のドキュメントを少しみてみます。

  • verified email addresses or domainsからしかメール送信できません。
  • もしAWSアカウントが、Amazon SES sandbox のままなら、verified email addressesか、 Amazon SES mailbox simulatorにしか送信できません。

今回は特定のメールアドレスのみへの送信でいいため、サンドボックスのまま利用します。
マネージメントコンソールでSESにメールアドレスを登録します。
すると、登録したメールアドレスに確認メールが来るので、そこに書かれたURLリンクをクリックするとverifidとなります。

  • 添付ファイルを含む最大メッセージサイズは10MBです。

添付ファイルのサイズが大きい時などは要注意ですね。
今回はLambdaで圧縮処理し、サイズを小さくしてから、メールに添付します。
「え、S3保存した時点で圧縮した方がいい?ですよね。」

Lambda

次にサンプルコードから変更が必要な箇所をみていきます。

送信元アドレスと宛先アドレスの設定

# Replace sender@example.com with your “From” address.
# This address must be verified with Amazon SES.
SENDER = Sender Name <sender@example.com>

# Replace recipient@example.com with a “To” address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = recipient@example.com

送信元アドレスと宛先アドレスは、SESでverifiedされたものに変更しましょう。

CONFIGURATION_SETの設定

# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
CONFIGURATION_SET = ConfigSet

SESの設定でConfiguration Setというのがあるのですが、それを指定します。
マネージメントコンソールで簡単に作成できるので、それを指定しても構いません。(設定値はデフォルトのままでOK)
または、サンプルコードの下の方にあるConfigurationSetName=CONFIGURATION_SET をコメントアウトしても動きます。

S3オブジェクトをローカルに一時保存してから添付する

S3オブジェクトを添付ファイルとして扱いたいのですが、直接S3オブジェクトのURLやARNは指定ができません。
Lambda関数が動いているローカルマシンのファイルシステムに一時的に保存した後で、それを添付ファイルとして指定します。
但し、Lambdaには、書き込み可能なディレクトリが /tmp のみという制限があります。

以下はs3オブジェクトをローカルに保存する例です。
例では、Bucket名/reports/yyyy/mm/xxxx.csv といった形で保存されているオブジェクトをdownload_fileで/tmpに保存し、zipfileで圧縮しています。
このコードはさておき、Lambdaでは/tmpにしか保存できないとだけ覚えておいていただければと思います。

そして、保存したファイルをATTACHMENTで指定します。

これで添付ファイル付きのメールを送信できるようになっています。
以下はAWS SDKs を使用して raw E メールを送信するを元にして作ったコードの全文となります。
(本題と関係ないため説明省略しましたが、datetimeとreとzipfileをimportしています。)

 

まとめ

  • SESで添付ファイルが必要な時は、send_raw_emailメソッドを使う。
  • SESで添付ファイルはs3オブジェクトを指定できないので、Lambdaに一時保存する。
  • Lambdaは/tmpにしかファイルを保存できない。
AWS運用自動化サービス「Cloud Automator」