これは、なにをしたくて書いたもの?
Amazon SESをローカルで動作確認できるような代替ツールはないのかな?と思って調べてみたのですが。
LocalStackはAmazon SES v1は使えますが、v2はProでないと利用できないようです。
aws-ses-v2-localというものがあるようなので、こちらを試してみることにしました。
Amazon SESのAPI
Amazon SES自体は、メールの送受信を行えるサービスです。
Amazon SESとは? - Amazon Simple Email Service
メール送信は、以下の3つの方法で行うことができます。
- Amazon SES APIを使う
- Amazon SES API を使用して E メールを送信する - Amazon Simple Email Service
SendEmail
、SendRawEmail
の2種類のAPIがある
- Amazon SES API を使用して E メールを送信する - Amazon Simple Email Service
- Amazon SES SMTPインターフェースを使う
- Amazon SESコンソールを使う
Amazon SESのE メール形式 - Amazon Simple Email Service
さらに、APIにはv1とv2があります。
Welcome - Amazon Simple Email Service
Welcome - Amazon Simple Email Service
LocalStackがサポートしていないのは、このv2です。
APIは、AWS SDKやAWS CLIなどから利用します。
Amazon SESとAWS SDKについての情報やサンプルは、こちらにまとまっています。
AWS SDK での Amazon SES の使用 - Amazon Simple Email Service
こちらのページからリンクされているAWS SDK for JavaScrpt v3のサンプルでは、v1のみでした。
https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javascriptv3/example_code/ses
AWS SDK for Java v2のサンプルでは、v2もv1もありました。
https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/javav2/example_code/ses
コード例のページ。
AWS SDK を使用した Amazon SES のコード例 - Amazon Simple Email Service
AWS SDK を使用した Amazon SES のコード例 - Amazon Simple Email Service
AWS SDK を使用した Amazon SES API v2 のコード例 - Amazon Simple Email Service
メール送信の例。
AWS SDK を使用して Amazon SES から E メールを送信する - Amazon Simple Email Service
AWS SDK を使用して Amazon SES API v2 E メールを送信する - Amazon Simple Email Service
aws-ses-v2-local
aws-ses-v2-localはAmazon SESのローカルバージョンで、APIはv1とv2の両方をサポートしています。
SendEmail
とSendRawEmail
の両方のエンドポイントに重点を置いています。
テキストメール、HTMLメールのどちらも扱え、添付ファイルもOK。送信されたメールのViewerも持っています。
今回はこちらを使って、Amazon SES API v2を使ったメールの送信を試してみたいと思います。クライアントは、AWS SDK for JavaScript v3を
使います。
環境
今回の環境は、こちら。
$ node --version v16.17.1 $ npm --version 8.15.0
AWS SDK for JavaScriptを使ったプログラムと、aws-ses-v2-localをインストールするディレクトリは別にします。
$ mkdir app tool
aws-ses-v2-localをインストールする
まずはaws-ses-v2-localをインストールします。この用途向けに作成したディレクトリ内に移動。
$ cd tool
インストール。
$ npm i aws-ses-v2-local
インストールされたバージョンは、こちら。
"dependencies": { "aws-ses-v2-local": "^2.0.1" }
起動方法は、aws-ses-v2-local
コマンドで起動するか、プログラム内で起動するかのどちらかです。
aws-ses-v2-local / Usage / Setting up aws-ses-v2-local
今回はaws-ses-v2-local
コマンドで起動することにします。
$ npx aws-ses-v2-local
標準出力に出ているとおり、http://localhost:8005
でリクエストを受け付けるようになります。
aws-ses-v2-local: starting server... aws-ses-v2-local: server running at http://localhost:8005
なお、ブラウザでhttp://localhost:8005
にアクセスするとWeb UIが表示されます。
もうひとつの起動方法は、以下のようにJavaScriptプログラム内で起動する方法ですね。
import server from 'aws-ses-v2-local' server({ port: 8005 }) console.log('aws-ses-v2-local: server up and running')
aws-ses-v2-localは、Expressを使って作られているようです。
https://github.com/domdomegg/aws-ses-v2-local/blob/v2.0.1/src/index.ts
aws-ses-v2-localにアクセスするプログラムを作成する
では、aws-ses-v2-localを使うプログラムを作成しましょう。といっても、AWS SDK for JavaScript v3を使ってのアクセスですが。
確認は、テストコードで行うことにします。
アプリケーション用のディレクトリ内に移動。
$ cd /path/to/app
Node.js+TypeScriptのプロジェクトのセットアップ。
$ npm init -y $ npm i -D typescript $ npm i -D prettier $ npm i -D @types/node@v16 $ npm i -D jest @types/jest $ npm i -D esbuild esbuild-jest $ mkdir src test
この時点での依存関係。
"devDependencies": { "@types/jest": "^29.0.3", "@types/node": "^16.11.60", "esbuild": "^0.15.9", "esbuild-jest": "^0.5.0", "jest": "^29.0.3", "prettier": "^2.7.1", "typescript": "^4.8.3" },
scripts
の定義。
"scripts": { "build": "tsc --project .", "build:watch": "tsc --project . --watch", "typecheck": "tsc --project ./tsconfig.typecheck.json", "typecheck:watch": "tsc --project ./tsconfig.typecheck.json --watch", "test": "jest", "format": "prettier --write src test" },
各種設定ファイル。
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "lib": ["esnext"], "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
tsconfig.typecheck.json
{ "extends": "./tsconfig", "compilerOptions": { "baseUrl": "./", "noEmit": true }, "include": [ "src", "test" ] }
.prettierrc.json
{ "singleQuote": true }
jest.config.js
module.exports = { testEnvironment: 'node', transform: { "^.+\\.tsx?$": "esbuild-jest" } };
あとは、AWS SDK for JavaScript v3をインストールします。
今回は、Amazon SES API v2用のクライアントをインストール。
$ npm i @aws-sdk/client-sesv2
SESv2 Client - AWS SDK for JavaScript v3
"dependencies": { "@aws-sdk/client-sesv2": "^3.178.0" }
これで、プログラムを書くまでの準備は完了です。
あとは、このあたりを参考にしつつ、プログラムを作成します。
aws-ses-v2-local / Usage / Setting up your application
作成したテストコード。
test/ses-v2-send-mail.test.ts
import { SendEmailCommand, SendEmailCommandInput, SESv2Client, } from '@aws-sdk/client-sesv2'; test('Amazon SES API v2, sendMail test', async () => { const ses = new SESv2Client({ endpoint: 'http://localhost:8005', region: 'us-east-1', credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy', }, }); const input: SendEmailCommandInput = { FromEmailAddress: 'from@example.com', Destination: { ToAddresses: ['to@example.com'] }, Content: { Simple: { Subject: { Data: 'メールの件名です', }, Body: { Text: { Data: `こんにちは。 Amazon SES v2 APIでSimpleメールを送ります。`, }, }, }, }, }; const command = new SendEmailCommand(input); const output = await ses.send(command); expect(output.MessageId).not.toBeUndefined(); expect(output.MessageId).toMatch(/^ses-\d+/); expect(output.$metadata.httpStatusCode).toBe(200); console.log(output); });
Amazon SES API v2を使う時に、エンドポイントをhttp://localhost:8005
(aws-ses-v2-localのエンドポイント)に指定する必要があります。
const ses = new SESv2Client({ endpoint: 'http://localhost:8005', region: 'us-east-1', credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy', }, });
クレデンシャルは設定しないとAWS SDK for JavaScript v3が動作しませんが、値自体はなんでも良さそうです。
SendMail
APIを使う際には、AWS SDK for JavaScript v3の以下あたりのAPIリファレンスを参照して書きました。
SendEmailCommand | SESv2 Client - AWS SDK for JavaScript v3
SendEmailCommandInput | SESv2 Client - AWS SDK for JavaScript v3
EmailContent | SESv2 Client - AWS SDK for JavaScript v3
Message | SESv2 Client - AWS SDK for JavaScript v3
動作確認
動かしてみます。
$ npm test
テストの結果。
> app@1.0.0 test > jest console.log { '$metadata': { httpStatusCode: 200, requestId: undefined, extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, MessageId: 'ses-338985724' } at Object.<anonymous> (test/ses-v2-send-mail.test.ts:34:11) PASS test/ses-v2-send-mail.test.ts ✓ Amazon SES API v2, sendMail test (68 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 0.574 s, estimated 1 s Ran all test suites.
SendEmailCommand
の実行結果はSendMailCommandOutput
ですが、aws-ses-v2-localの場合はどんなレスポンスが返ってきているか
わかるように、console.log
で出力もしています。
{ '$metadata': { httpStatusCode: 200, requestId: undefined, extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, MessageId: 'ses-338985724' }
SendEmailCommandOutput | SESv2 Client - AWS SDK for JavaScript v3
メールを送信した後、http://localhost:8005/
にアクセスするとaws-ses-v2-localのWeb UI上で送信されたメールを確認できます。
さらにメールを追加。
タイムスタンプの新しい方から上に並んでいきます。
aws-ses-v2-localに送信されたメールは配列で保持しているので、再起動するとデータがなくなります。まあ、困らないでしょうけれど。
https://github.com/domdomegg/aws-ses-v2-local/blob/v2.0.1/src/store.ts#L23-L25
こんな感じでしょうか。
まとめ
aws-ses-v2-localを使って、Amazon SES API v2を試してみました。
SendEmail
の方しか試していませんが、割と簡単に使えたので良さそうです。
SendRawEmail
やその他の機能は、また気になった時に試すことにします。