はじめに
AWS SES を使用したアプリケーションを開発する場合、テストやローカル環境などでメールを送信できるようにするため、ローカルな SES サーバーを立ち上げて使用することがあると思います。
これは、 SES だけに言えることではなく、S3 など他の AWS ソリューションでもローカルで立ち上げることができます。そして、 AWS をローカルでエミュレートするアプリケーションは多くありますが一番使われているのは LocalStack ではないでしょうか?
S3 などでは LocalStack を使えば特に問題はないのです。ですが、 AWS SES だけ問題があります。実際に LocalStack のドキュメントを見てみると、
SESv1 is available in LocalStack Community image, while SESv2 and SMTP integration is available in LocalStack Pro. The supported APIs are available on the API coverage page for SESv1 and SESv2.
Simple Email Service (SES) | Docs
はい、なんと、 AWS SES API V2 経由 LocalStack で SES を使いたい場合は LocalStack Pro プランが必要なんですよね*1。
しかし、SESのためだけに Pro になるのは…… というケースのために GitHub - domdomegg/aws-ses-v2-local: ☁📬 A local version of Amazon Simple Email Service (AWS SES) supporting the V1 and V2 API を使用したローカル SES サーバーの立ち上げ方について紹介します。
aws-ses-v2-local とは?
AWS SES をローカルでエミュレートできるツールです。API の受取部として動作します。実際にここからメール送信などは行えず、専用のダッシュボードが用意されていて、そこで API 経由で受け取ったメールが表示される仕組みになっています。地味にダッシュボードはリッチになっていてダークモードとかにも対応しているっぽい、すごい。
特筆するポイントとして、 V1 と V2 どちらの API にも対応しています。
Note
ちなみに、送信されたメールの保存先はインメモリのようなので再起動するとデータはすべて消えてしまうようです。
簡単な使い方
このアプリケーションは node.js で作られていて、npm にアップロードされているため、 npm
経由で簡単にインストールが可能です。
npm i -g aws-ses-v2-local
aws-ses-v2-local
これでもいいですが、これだけなら npx
を使えば1行で実行することができます。
npx -y aws-ses-v2-local
この状態で http://localhost:8005
にアクセスすることでダッシュボードが確認できるかと思います。
Tip
aws-ses-v2-local はデフォルトで
[::1]:8005
を受け付けるらしいです。[::1]
は IPv6 のループバックアドレスなので、 IPv4 でしか対応していない環境などではアクセスできません。そのため、明示的に0.0.0.0
を指定して IPv4 で受け付けるといいです。npx -y aws-ses-v2-local --host 0.0.0.0
アプリケーション側では、以下のようにエンドポイントを localhost:8005
とすることで aws-ses-v2-local にメールを送信することが可能になります。以下は Go での実装例です。
package main import ( "context" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/sesv2" ) func main() { ctx := context.Background() awsConfig := config.LoadDefaultConfig( ctx, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("test", "test", "test")), config.WithRegion("ap-northeast-1"), ) // ここを localhost にする endpoint := "http://localhost:8005" client := sesv2.NewFromConfig(awsConfig, func(o *sesv2.Options) { // BaseEndpoint を上書きすることで、APIの送信先を変更することができる o.BaseEndpoint = endpoint }) input := &sesv2.SendEmailInput{ ... } _, err := client.SendEmail(ctx, input) if err != nil { panic(err) } }
Dockerfile
さて、これを Docker で利用する方法についても解説しましょう。
FROM node:22 WORKDIR /app EXPOSE 8005:8005 CMD ["npx", "-y", "aws-ses-v2-local", "--host", "0.0.0.0"]
特にむずかしくないです。 node のベースイメージはとりあえず現時点での最新版を使えばいいと思います。
さらに、compose.yaml で定義する場合は以下のようにします。この例では、inline で image
, command
, working_dir
を指定してしまっていますが、別で Dockerfile を作って build
を使って指定することも可能です。
version: '3' services: ses-local: container_name: ses-local image: node:22 working_dir: /app command: ["npx", "-y", "aws-ses-v2-local", "--host", "0.0.0.0"] ports: - "8005:8005" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8005/health-check"]
オススメポイントとして、http://localhost:8005/health-check
が用意されていて、サーバーの準備が完了すると Response 200 で応答が返ってきます。これを docker compose の healthcheck で確認することで depends_on
で簡単に依存を定義することが可能となります。
depends_on
で healthcheck を利用する方法は過去にエントリを書いているのでぜひ参考にしてみてください。
参考文献
- aws-ses-v2-localを使って、Amazon SES API v2をローカルで試す - CLOVER🍀
- aws-ses-v2-localを使ってローカルでSESのAPIを使ってメール送信
- aws-ses-v2-local/docker-compose.example.yaml at master · domdomegg/aws-ses-v2-local · GitHub
*1:Proを使えるのであれば、こちらを使用したほうが絶対良い