概要
SesV2Clientを使って、メールテンプレート登録、一括送信機能を実装しました。意外とドキュメントにも書いていないことがあったので、役にたてばと思い記事を書きます。
この記事で伝えたいこと
- ローカル環境でSDKを使ってメール送信機能を実装する手順
- 初見のAWSサービスを使うときのアプローチの仕方
前提
- ローカルでSES APIを使うためのコンテナ作成
- CLIコマンドの準備
(ローカル環境の参考はこちら https://zenn.dev/machui/articles/bfd998c086d81f)
(CLIコマンド準備 https://zenn.dev/hayato94087/articles/7848e9d6a2e3d6)
メールテンプレート登録、一括送信をSDKで実装するときの流れ(ローカル環境)
- まずAWS CLIで動くか確かめる
- エラーが出るので必要な項目、必要な形式がわかる。
- SDKに直して、実装する。
初めからSDKを使った方が早いように思えますが、上記の手順で必要な項目を絞っていくのが一番早い気がします。急がば回れってことですね。
CLIコマンドでテンプレート登録、一括送信を行うときのCLIコマンドは下記の通りです。事前にtest.json testbulk.jsonファイルを作成しておく必要があります。
//テンプレート登録
aws sesv2 create-email-template --endpoint-url http://localhost:8005/ --cli-input-json file://test.json --debug
//テンプレート一括送信
aws sesv2 send-bulk-email --endpoint-url http://localhost:8005 --cli-input-json file://testbulk.json --debug
//test.json
{
"TemplateName": "TemplateToShareholders",
"TemplateContent": {
"Subject": "株主総会のお知らせ",
"Text": "株主総会のお知らせ {{name}}様 登録番号{{registaration_number}}",
"Html": "test"
}
}
//testbulk.json
{
"FromEmailAddress": "test@example.com",
"DefaultContent": {
"Template": {
"TemplateName": "TemplateToShareholders",
"TemplateArn": ""
}
},
"BulkEmailEntries": [
{
"Destination": {
"ToAddresses": [
"send1@example.com"
],
"CcAddresses": [],
"BccAddresses": []
},
"ReplacementEmailContent": {
"ReplacementTemplate": {
"ReplacementTemplateData": "[{ \"Name\": \"name\", \"Value\": \"鈴木\" }, { \"Name\": \"registration_number\", \"Value\": \"11111\" }]"
}
}
},
//送り先の数だけDestinationとReplacementContentのセットが必要になる。
]
}
テンプレート作成時に置換したい文言は{{name}}のように記述して、登録します。一括送信時に、nameとvalueをそれぞれ指定することで置換して、送信されるという流れになります。
{
"BulkEmailEntryResults": [
{
"Status": "SUCCESS",
"MessageId": "ses-530454411"
},
{
"Status": "SUCCESS",
"MessageId": "ses-340155346"
}
]
}
(END)
既出のsend-bulk-emailコマンドが成功すると、ターミナルで上記のような記述が出ます。
SDKで置き換える
AWS CLIで必要な項目がわかったので、次にSDKで実装していきます。送信機能は登録、編集、一括送信をまとめて実装することが多いと思います。なのでMail**.phpのようなクラスを設けて機能ごとにメソッドを作っていくのがやりやすいかと思います。
public function registerMailTemplate(array $request): void
{
try {
$this->sesClient->createEmailTemplate([
'TemplateContent' => [
'Subject' => $request['subject'], //リクエストボディ.メール題名
'Text' => $request['mail_text'],//リクエストボディ.本文のテキスト
],
'TemplateName' => $request['subject'],
]);
} catch (SesV2Exception $e) {
throw new SimpleEmailServiceException();
}
}
下記のコードで動きましたが、実際200になるようにキーの取捨選択をするにかなり時間を要しました。まずはドキュメントを見てみましょう。
$result = $client->sendBulkEmail([
'BulkEmailEntries' => [ // REQUIRED
[
'Destination' => [ // REQUIRED
'BccAddresses' => ['<string>', ...],
'CcAddresses' => ['<string>', ...],
'ToAddresses' => ['<string>', ...],
],
'ReplacementEmailContent' => [
'ReplacementTemplate' => [
'ReplacementTemplateData' => '<string>',
],
],
'ReplacementHeaders' => [
[
'Name' => '<string>', // REQUIRED
'Value' => '<string>', // REQUIRED
],
// ...
],
'ReplacementTags' => [
[
'Name' => '<string>', // REQUIRED
'Value' => '<string>', // REQUIRED
],
// ...
],
],
// ...
],
'ConfigurationSetName' => '<string>',
'DefaultContent' => [ // REQUIRED
'Template' => [
'Headers' => [
[
'Name' => '<string>', // REQUIRED
'Value' => '<string>', // REQUIRED
],
// ...
],
'TemplateArn' => '<string>',
'TemplateData' => '<string>',
'TemplateName' => '<string>',
],
],
'DefaultEmailTags' => [
[
'Name' => '<string>', // REQUIRED
'Value' => '<string>', // REQUIRED
],
// ...
],
'FeedbackForwardingEmailAddress' => '<string>',
'FeedbackForwardingEmailAddressIdentityArn' => '<string>',
'FromEmailAddress' => '<string>',
'FromEmailAddressIdentityArn' => '<string>',
'ReplyToAddresses' => ['<string>', ...],
]);
(上記 参照元https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.SesV2.SesV2Client.html)
requiredの項目がたくさんありますね。これらは必須項目として、全部記述する必要はありません。最初は上記を見てREQUIREDを描かれている項目は必須なのかと思い、REQUIREDの項目は全て入力した上で実行していました。しかし当然全ての項目をボディから賄えるはずもなく、'test'のような仮の項目で書いていました。次に実際にローカルで動いたコードを見てましょう。
public function sendBulkEmail ()
{
try {
$this->sesClient->sendBulkEmail(
[
'FromEmailAddress' => config('mail.from.name') . '<' . config('mail.from.address') . '>',
'DefaultContent' => [
'Template' => [
'TemplateName' => $templateName,
'TemplateData' => $this->getTemplateDataJson($defaultTemplateData),
]
],
'BulkEmailEntries' => $bulkEmailEntries
]
);
} catch (SesV2Exception $e) {
Log::error('SES sendbulk error', [
'ses error' => $e->getMessage(),
'file' => $e->getFile(),
'Line' => $e->getLine(),
'Trace' => $e->getTraceAsString(),
]);
// 送信に失敗したユーザ、未送信のユーザリストログ
Log::info('ses', [
'message' => 'SES bulk send users failed to send and users not sending',
'failed_user_ids' => $userIds,
'action' => 'SendBulkEmail'
]);
throw new SimpleEmailServiceException();
}
}
ドキュメントの項目よりもだいぶ項目は削りました。
結論を言うと、小項目が必須になるのは関連する大項目がある場合だけです。なので、今回sendBulkEmailを実行する上で、必要な項目はBulkEmailEntries以下ならDestinationだけです。それから必要なのはTemplateData, TemplateName, FromEmailAddressです。TemplateNameなどに至ってはrequiredは書いてないですが、自明ゆえにrequiredになっていないのかもしれません。
初めて触るサービスで上手くいかないときの、アプローチの仕方
これに関してはSESに限らない話ですが、初見のサービスを触るときに公式ドキュメント通りに実行しても上手くいかないときがあります。その時にどうアプローチしたら、楽にそのハードルをクリアできるのか。今回sesを触って重要だと感じたのは、次の点です。
- 一次情報を探す
(ここでいう一次情報は、公式ドキュメント、パッケージのソースコードを指します。) - 積極的にデバッグする
今回でいえば、ドキュメント通りでも動かず、aws-ses-v2-localのソースコードをデバッグして必要な項目、形式がわかりました。リクエスト送った結果、どこまで処理がいっているか確かめたい時はデバッグコードを足して、もう一度コンテナをビルドし直すといいです。どこまで処理がいっているかログを見れば確認ができます。
以上、SDKforphpを使ったテンプレート登録、一括送信機能についての振り返りでした。誰かしらの参考になったら幸いです。