Memo

メモ > サーバ > サービス: AWS > SES メール送信ログの設定

■SES メール送信ログの設定
Amazon SESには、メール送信ログを確認する方法が提供されていない Amazon OpenSearch Service や Amazon Elasticsearch Service に記録することはできるらしい Amazon SES の E メール送信履歴の保存と表示 https://aws.amazon.com/jp/premiumsupport/knowledge-center/ses-email-sending-history/ Amazon SES でのメール送信ログを表示する - DENET 技術ブログ https://blog.denet.co.jp/amazon-ses-log/ Amazon SESのメール送信ログを記録する - サーバーワークスエンジニアブログ https://blog.serverworks.co.jp/2020/12/04/190000 Amazon OpenSearch Service は高額らしいので、S3に保存している例もある ただしこの場合、S3に保存されたログを確認する手段を自分で用意する必要がある SESの送信履歴を確認したい https://zenn.dev/isseeeeey55/articles/61b350c27e1040 SES のログを S3 に出力してバウンスメールを確認してみる - Qiita https://qiita.com/sugimount-a/items/f9202c676514dcd3d182 Kinesis Data Firehose をゼロからざっくり理解する | DevelopersIO https://dev.classmethod.jp/articles/amazon-kinesis-data-firehose-for-beginner/ 以下は発展形としていつか参考になるかも…くらい そのメール、本当に届いてる?Amazon SESの運用で得た監視プラクティス - Cybozu Inside Out | サイボウズエンジニアのブログ https://blog.cybozu.io/entry/2021/11/26/075846 以下を参考に、実際にS3へのログ転送を試してみる 【AWS】AWS SESのログをKinesis Data Firehose経由でS3へ転送してみました - Qiita https://qiita.com/hyj624117615/items/6bf44f2f86c252e3e00b s3のライフサイクルルールを設定してみる - Qiita https://qiita.com/miyuki_samitani/items/cbea495fb116b5bf5db6 以下はS3への保存では無いが、部分的には参考になる SESのメール送信履歴をOpenSearch Serviceで表示してみた | DevelopersIO https://dev.classmethod.jp/articles/ses-visualisation-email-sending-history-with-opensearch-service/ 【AWS】AWS SESのログをKinesis Data Firehose経由でS3へ転送してみました - Qiita https://qiita.com/hyj624117615/items/6bf44f2f86c252e3e00b ■S3にバケットを作成 S3 → バケットを作成 バケット名: refirio-ses-log AWSリージョン: アジアパシフィック(東京) このバケットのブロックパブリックアクセス設定: パブリックアクセスをすべて ブロック ※「バケットのバージョニング」はデフォルトのまま(無効)とした 「デフォルトの暗号化」はデフォルトのまま(SSE-S3 / 有効にする)とした ■Kinesis Data Firehoseに配信ストリームを作成 Kinesis Data Firehose → 配信ストリームを作成 ソース: Direct PUT 送信先: Amazon S3 配信ストリーム名: refirio-ses-kinesis S3バケット: s3://refirio-ses-log S3バケットプレフィックス: ses-log- S3バケットエラー出力プレフィックス: ses-log-error- バッファ間隔: 60 ※「S3バケット」は上で作成したものを選択 「バッファ間隔」は検証のために60にした。本番運用なら、300のままでいいかもしれない ※「許可」はデフォルトのまま「IAM ロール KinesisFirehoseServiceRole-refirio-ap-northeast-1-1234567890123 を作成または更新」を選択したが、 すでに作成したものがあるならそれを使えば良さそう(2回目以降に作成する場合など) 作成すると「refirio-ses-kinesis の作成中。ステータスが更新されるまでに最大5分かかる場合があります。」と表示されるので待つ 「配信ストリームを作成」ボタン押して以下のエラーが作成された場合、作業しているユーザの権限を確認する
配信ストリームは作成されませんでした 配信ストリーム refirio-ses-kinesis の作成に必要な許可がありません。IAM 許可を確認して変更し、このユーザーに必要な許可が付与されているようにしてください。 アクション: iamadmin:CreateServiceRole/CreatePolicyForServiceRole/UpdateServiceRolePolicy ユーザー: arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_PowerUserAccess_1db0a2445f639f21/refirio APIレスポンス: User: arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_PowerUserAccess_1db0a2445f639f21/refirio is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::123456789012:role/service-role/KinesisFirehoseServiceRole-refirio-ap-northeast-1-1674707361061 because no identity-based policy allows the iam:CreateRole action
■SESを設定 Amazon Simple Email Service → 設定セット → セットの作成 設定セット名: refirio-ses-log ※設定セットは引き続きの設定が必要だが、このタイミングでいったんIAMポリシーとIAMロールを作成する ■IAMポリシーを作成 Identity and Access Management (IAM) → ポリシー → ポリシーの作成 「JSON」タブで以下を入力する
{ "Version": "2012-10-17", "Statement": [ { "Sid": "0", "Effect": "Allow", "Action": "firehose:ListDeliveryStreams", "Resource": "*" }, { "Sid": "1", "Effect": "Allow", "Action": "firehose:*", "Resource": "arn:aws:firehose:*:123456789012:deliverystream/*" } ] }
※「123456789012」部分にはAWSのIDを入力する 名前: ses-log-policy これでポリシーを作成する ■IAMロールを作成 Identity and Access Management (IAM) → ロール → ロールを作成 「信頼されたエンティティタイプ」で「カスタム信頼ポリシー」を選択し、表示される「カスタム信頼ポリシー」欄に以下を入力する
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "ses.amazonaws.com" ] }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "AWS:SourceAccount": "123456789012", "AWS:SourceArn": "arn:aws:ses:ap-northeast-1:123456789012:configuration-set/refirio-ses-log" } } } ] }
※「123456789012」部分にはAWSのIDを、「refirio-ses-log」部分には設定セット名をそれぞれ入力する 「許可を追加」で「IAMポリシーを作成」の手順で作成したポリシー(ses-log-policy)を選択 名前: ses-log-role これでロールを作成する ■SESを設定(続き) Amazon Simple Email Service → 設定セット → refirio-ses-log → イベント送信先 → 送信先の追加 ※「refirio-ses-log」は上の手順で作成した設定セット 今回はイベントタイプの選択で 「送信」「拒否」「配信」「ハードバウンス」「苦情数」「配信の遅延」「サブスクリプション」 にチェックを入れてみる ※イベントタイプの内容を絞ることでコストを最適化できるみたい 送信先の指定は 送信先タイプ: Amazon Kinesis Data Firehose 名前: refirio-ses-log 配信ストリーム: refirio-ses-kinesis Identity and Access Management (IAM) ロール: ses-log-role ※「配信ストリーム」は上で作成したものを選択 ※「Identity and Access Management (IAM) ロール」は上で作成したものを選択 ■メール送信テスト Amazon Simple Email Service → 検証済みID → refirio.net → テストEメールの送信 Eメール形式: フォーマット済み From-address: info@refirio.net シナリオ: 配信の成功 件名: 送信テスト 本文: これは送信テストです。 設定セット: refirio-ses-log ※「設定セット」は上で作成したものを選択 「テストEメールの送信」ボタンをクリック(実際にメールは送信されない) 2〜3分ほど待つと、refirio-ses-log バケット内にフォルダが作成された refirio-ses-log/ses-log-2023/01/26/06/refirio-ses-kinesis-1-2023-01-26-06-32-55-4459a487-45e3-41ad-80ca-d53999eeddc2
{"eventType":"Delivery","mail":{"timestamp":"2023-01-26T06:32:14.171Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185ecc6de5b-7376664e-c6e8-4a33-9d11-a8f8be738b5e-000000","destination":["success@simulator.amazonses.com"],"headersTruncated":false,"headers":[{"name":"From","value":"info@refirio.net"},{"name":"To","value":"success@simulator.amazonses.com"},{"name":"Subject","value":"送信テスト"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative; boundary=\"----=_Part_80348_1716894568.1674714734175\""}],"commonHeaders":{"from":["info@refirio.net"],"to":["success@simulator.amazonses.com"],"messageId":"01060185ecc6de5b-7376664e-c6e8-4a33-9d11-a8f8be738b5e-000000","subject":"送信テスト"},"tags":{"ses:operation":["SendEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["203.0.113.1"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["refirio-user"],"ses:outgoing-ip":["23.251.234.1"]}},"delivery":{"timestamp":"2023-01-26T06:32:15.224Z","processingTimeMillis":1053,"recipients":["success@simulator.amazonses.com"],"smtpResponse":"250 2.6.0 Message received","reportingMTA":"e234-1.smtp-out.ap-northeast-1.amazonses.com"}} {"eventType":"Send","mail":{"timestamp":"2023-01-26T06:32:14.171Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185ecc6de5b-7376664e-c6e8-4a33-9d11-a8f8be738b5e-000000","destination":["success@simulator.amazonses.com"],"headersTruncated":false,"headers":[{"name":"From","value":"info@refirio.net"},{"name":"To","value":"success@simulator.amazonses.com"},{"name":"Subject","value":"送信テスト"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative; boundary=\"----=_Part_80348_1716894568.1674714734175\""}],"commonHeaders":{"from":["info@refirio.net"],"to":["success@simulator.amazonses.com"],"messageId":"01060185ecc6de5b-7376664e-c6e8-4a33-9d11-a8f8be738b5e-000000","subject":"送信テスト"},"tags":{"ses:operation":["SendEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["203.0.113.1"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["refirio-user"]}},"send":{}}
それらしいものが格納されている 再度テストEメールを送信してみる。今回はシナリオで「バウンス」を選択して送信してみる 2〜3分ほど待つと、新たにファイルが作成された refirio-ses-log/ses-log-2023/01/26/06/refirio-ses-kinesis-1-2023-01-26-06-38-14-c5d40628-51e3-4636-88e9-681b3e08ac53
{"eventType":"Send","mail":{"timestamp":"2023-01-26T06:37:30.930Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185eccbb3b2-7b3a8bc1-aebd-4f35-b385-369eb6fd1691-000000","destination":["bounce@simulator.amazonses.com"],"headersTruncated":false,"headers":[{"name":"From","value":"info@refirio.net"},{"name":"To","value":"bounce@simulator.amazonses.com"},{"name":"Subject","value":"送信テスト(バウンス)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative; boundary=\"----=_Part_3104396_282462092.1674715050933\""}],"commonHeaders":{"from":["info@refirio.net"],"to":["bounce@simulator.amazonses.com"],"messageId":"01060185eccbb3b2-7b3a8bc1-aebd-4f35-b385-369eb6fd1691-000000","subject":"送信テスト(バウンス)"},"tags":{"ses:operation":["SendEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["203.0.113.1"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["refirio-user"]}},"send":{}} {"eventType":"Bounce","bounce":{"feedbackId":"01060185eccbb630-c60c6634-7090-4b79-aabc-b6e2b08d9af2-000000","bounceType":"Permanent","bounceSubType":"General","bouncedRecipients":[{"emailAddress":"bounce@simulator.amazonses.com","action":"failed","status":"5.1.1","diagnosticCode":"smtp; 550 5.1.1 user unknown"}],"timestamp":"2023-01-26T06:37:31.687Z","reportingMTA":"dns; e234-2.smtp-out.ap-northeast-1.amazonses.com"},"mail":{"timestamp":"2023-01-26T06:37:30.930Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185eccbb3b2-7b3a8bc1-aebd-4f35-b385-369eb6fd1691-000000","destination":["bounce@simulator.amazonses.com"],"headersTruncated":false,"headers":[{"name":"From","value":"info@refirio.net"},{"name":"To","value":"bounce@simulator.amazonses.com"},{"name":"Subject","value":"送信テスト(バウンス)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"multipart/alternative; boundary=\"----=_Part_3104396_282462092.1674715050933\""}],"commonHeaders":{"from":["info@refirio.net"],"to":["bounce@simulator.amazonses.com"],"messageId":"01060185eccbb3b2-7b3a8bc1-aebd-4f35-b385-369eb6fd1691-000000","subject":"送信テスト(バウンス)"},"tags":{"ses:operation":["SendEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["203.0.113.1"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["refirio-user"]}}}
「メール1送信=1ファイル」でログが作成されている ■デフォルト設定セットの割り当て Amazon Simple Email Service → 検証済みID → refirio.net → 設定セット → 編集 デフォルト設定セットの割り当て: (チェックを入れる) デフォルト設定セット: refirio-ses-log ※「デフォルト設定セット」は上で作成したものを選択 これでメール送信時に「設定セット」を指定しなくても、自動的に設定セットが割り当てられる SMTPからのメール送信なども、自動的に設定セットが使用される ■古いログの自動削除 S3 → refirio-ses-log → 管理 → ライフサイクルルールを作成する ライフサイクルルール名: refirio-ses-log-delete ルールスコープを選択: バケット内のすべてのオブジェクトに適用 バケット内のすべてのオブジェクトに適用: (チェックを入れる) ライフサイクルルールのアクション: オブジェクトの現行バージョンを有効期限切れにする オブジェクト作成後の日数: 3 ※アクションは「有効期限切れ=S3から削除される」ということらしい 「オブジェクト作成後の日数」は検証のために3にした。本番運用なら、90(=3ヶ月)など適宜設定する ※本当に削除されるか確認したところ、 ・2023/01/26 03:30 のファイル(12:30 のファイル)で確認 ・2023/01/30 時点で削除されずに残っていた ・2023/01/31 時点で削除されていた となっていた。ピッタリ3日では無いようだが、自動的に削除されていることは確認できた ■Postfix経由での送信 「SES PostfixからSMTPでメールを送信」の手順をもとに、Postfixを経由してSESからメール送信できるようにする また、外部からPostfixのアカウントを経由してSESからメール送信できるようにもする この状態で送信テストし、どのようにログが記録されるか確認 外部のPHPからSMTPを直接叩いてメール送信した場合、S3には以下のログが記録された
{"eventType":"Delivery","mail":{"timestamp":"2023-01-27T02:36:17.921Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185f1153881-050e347e-1c63-4627-a941-b146682babf0-000000","destination":["example@gmail.com"],"headersTruncated":false,"headers":[{"name":"Received","value":"from localhost (example.com [203.0.113.1]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-EQ3QJVK0M) id MAvuw8Xe28pKGsVJ1b6I for example@gmail.com; Fri, 27 Jan 2023 02:36:17 +0000 (UTC)"},{"name":"Date","value":"Fri, 27 Jan 2023 11:36:17 +0900"},{"name":"To","value":"メール受信者 <example@gmail.com>"},{"name":"From","value":"メール送信者 <info@refirio.net>"},{"name":"Subject","value":"外部SMTPからの送信テスト"},{"name":"Message-ID","value":"<0b123d8412043e673ccc717b26354311@localhost>"},{"name":"X-Mailer","value":"PHPMailer 5.2.19 (https://github.com/PHPMailer/PHPMailer)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Content-Transfer-Encoding","value":"base64"}],"commonHeaders":{"from":["\"メール送信者\" <info@refirio.net>"],"date":"Fri, 27 Jan 2023 11:36:17 +0900","to":["\"メール受信者\" <example@gmail.com>"],"messageId":"01060185f1153881-050e347e-1c63-4627-a941-b146682babf0-000000","subject":"外部SMTPからの送信テスト"},"tags":{"ses:operation":["SendSmtpEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["203.0.113.1"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["cre-test-smtp-user.20220726"],"ses:outgoing-ip":["23.251.234.3"]}},"delivery":{"timestamp":"2023-01-27T02:36:19.434Z","processingTimeMillis":1513,"recipients":["example@gmail.com"],"smtpResponse":"250 2.0.0 OK 1674786979 m3-20020a17090a730300b002297f945cf0si3008883pjk.57 - gsmtp","reportingMTA":"e234-3.smtp-out.ap-northeast-1.amazonses.com"}} {"eventType":"Send","mail":{"timestamp":"2023-01-27T02:36:17.921Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185f1153881-050e347e-1c63-4627-a941-b146682babf0-000000","destination":["example@gmail.com"],"headersTruncated":false,"headers":[{"name":"Received","value":"from localhost (example.com [203.0.113.1]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-EQ3QJVK0M) id MAvuw8Xe28pKGsVJ1b6I for example@gmail.com; Fri, 27 Jan 2023 02:36:17 +0000 (UTC)"},{"name":"Date","value":"Fri, 27 Jan 2023 11:36:17 +0900"},{"name":"To","value":"メール受信者 <example@gmail.com>"},{"name":"From","value":"メール送信者 <info@refirio.net>"},{"name":"Subject","value":"外部SMTPからの送信テスト"},{"name":"Message-ID","value":"<0b123d8412043e673ccc717b26354311@localhost>"},{"name":"X-Mailer","value":"PHPMailer 5.2.19 (https://github.com/PHPMailer/PHPMailer)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Content-Transfer-Encoding","value":"base64"}],"commonHeaders":{"from":["\"メール送信者\" <info@refirio.net>"],"date":"Fri, 27 Jan 2023 11:36:17 +0900","to":["\"メール受信者\" <example@gmail.com>"],"messageId":"01060185f1153881-050e347e-1c63-4627-a941-b146682babf0-000000","subject":"外部SMTPからの送信テスト"},"tags":{"ses:operation":["SendSmtpEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["203.0.113.1"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["cre-test-smtp-user.20220726"]}},"send":{}}
EC2を経由していないので、EC2の /var/log/maillog には何も記録されていない 外部のPHPからEC2経由でメール送信した場合、S3には以下のログが記録された
{"eventType":"Delivery","mail":{"timestamp":"2023-01-27T02:36:51.061Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185f115b9f5-0a7e240a-54ef-49e9-9725-b77a002bd950-000000","destination":["example@gmail.com"],"headersTruncated":false,"headers":[{"name":"Received","value":"from refirio.net (ec2-3-113-235-47.ap-northeast-1.compute.amazonaws.com [3.113.235.47]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-1B60FHL0M) id BqzsiwDa4Rkwhg0fCpCS for example@gmail.com; Fri, 27 Jan 2023 02:36:51 +0000 (UTC)"},{"name":"Received","value":"from localhost (example.com [203.0.113.1]) by refirio.net (Postfix) with ESMTPA id BAF64CAF15C for <example@gmail.com>; Fri, 27 Jan 2023 11:36:50 +0900 (JST)"},{"name":"Date","value":"Fri, 27 Jan 2023 11:36:50 +0900"},{"name":"To","value":"メール受信者 <example@gmail.com>"},{"name":"From","value":"メール送信者 <info@refirio.net>"},{"name":"Subject","value":"外部SMTPからの送信テスト2"},{"name":"Message-ID","value":"<5e0f33a5a5e0e2bed18ad4a102047b1e@localhost>"},{"name":"X-Mailer","value":"PHPMailer 5.2.19 (https://github.com/PHPMailer/PHPMailer)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Content-Transfer-Encoding","value":"base64"}],"commonHeaders":{"from":["\"メール送信者\" <info@refirio.net>"],"date":"Fri, 27 Jan 2023 11:36:50 +0900","to":["\"メール受信者\" <example@gmail.com>"],"messageId":"01060185f115b9f5-0a7e240a-54ef-49e9-9725-b77a002bd950-000000","subject":"外部SMTPからの送信テスト2"},"tags":{"ses:operation":["SendSmtpEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["3.113.235.47"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["cre-test-smtp-user.20220726"],"ses:outgoing-ip":["23.251.234.5"]}},"delivery":{"timestamp":"2023-01-27T02:36:52.514Z","processingTimeMillis":1453,"recipients":["example@gmail.com"],"smtpResponse":"250 2.0.0 OK 1674787012 12-20020a17090a034c00b002264d5dfc15si6926883pjf.113 - gsmtp","reportingMTA":"e234-5.smtp-out.ap-northeast-1.amazonses.com"}} {"eventType":"Send","mail":{"timestamp":"2023-01-27T02:36:51.061Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185f115b9f5-0a7e240a-54ef-49e9-9725-b77a002bd950-000000","destination":["example@gmail.com"],"headersTruncated":false,"headers":[{"name":"Received","value":"from refirio.net (ec2-3-113-235-47.ap-northeast-1.compute.amazonaws.com [3.113.235.47]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-1B60FHL0M) id BqzsiwDa4Rkwhg0fCpCS for example@gmail.com; Fri, 27 Jan 2023 02:36:51 +0000 (UTC)"},{"name":"Received","value":"from localhost (example.com [203.0.113.1]) by refirio.net (Postfix) with ESMTPA id BAF64CAF15C for <example@gmail.com>; Fri, 27 Jan 2023 11:36:50 +0900 (JST)"},{"name":"Date","value":"Fri, 27 Jan 2023 11:36:50 +0900"},{"name":"To","value":"メール受信者 <example@gmail.com>"},{"name":"From","value":"メール送信者 <info@refirio.net>"},{"name":"Subject","value":"外部SMTPからの送信テスト2"},{"name":"Message-ID","value":"<5e0f33a5a5e0e2bed18ad4a102047b1e@localhost>"},{"name":"X-Mailer","value":"PHPMailer 5.2.19 (https://github.com/PHPMailer/PHPMailer)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Content-Transfer-Encoding","value":"base64"}],"commonHeaders":{"from":["\"メール送信者\" <info@refirio.net>"],"date":"Fri, 27 Jan 2023 11:36:50 +0900","to":["\"メール受信者\" <example@gmail.com>"],"messageId":"01060185f115b9f5-0a7e240a-54ef-49e9-9725-b77a002bd950-000000","subject":"外部SMTPからの送信テスト2"},"tags":{"ses:operation":["SendSmtpEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["3.113.235.47"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["cre-test-smtp-user.20220726"]}},"send":{}}
EC2の /var/log/maillog には以下のとおり送信成功が記録されている
Jan 27 11:36:50 ip-10-1-0-47 postfix/smtpd[3863]: connect from example.com[203.0.113.1] Jan 27 11:36:50 ip-10-1-0-47 postfix/smtpd[3863]: BAF64CAF15C: client=example.com[203.0.113.1], sasl_method=LOGIN, sasl_username=info@refirio.net Jan 27 11:36:50 ip-10-1-0-47 postfix/cleanup[3867]: BAF64CAF15C: message-id=<5e0f33a5a5e0e2bed18ad4a102047b1e@localhost> Jan 27 11:36:50 ip-10-1-0-47 postfix/qmgr[3857]: BAF64CAF15C: from=<info@refirio.net>, size=795, nrcpt=1 (queue active) Jan 27 11:36:50 ip-10-1-0-47 postfix/smtpd[3863]: disconnect from example.com[203.0.113.1] Jan 27 11:36:50 ip-10-1-0-47 postfix/smtp[3868]: Trusted TLS connection established to email-smtp.ap-northeast-1.amazonaws.com[203.0.113.2]:587: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits) Jan 27 11:36:51 ip-10-1-0-47 postfix/smtp[3868]: BAF64CAF15C: to=<example@gmail.com>, relay=email-smtp.ap-northeast-1.amazonaws.com[203.0.113.2]:587, delay=0.52, delays=0.11/0.02/0.14/0.25, dsn=2.0.0, status=sent (250 Ok 01060185f115b9f5-0a7e240a-54ef-49e9-9725-b77a002bd950-000000) Jan 27 11:36:51 ip-10-1-0-47 postfix/qmgr[3857]: BAF64CAF15C: removed
存在しないメールアドレスに対して、外部のPHPからEC2経由でメール送信した場合、S3には以下のログが記録された
{"eventType":"Bounce","bounce":{"feedbackId":"01060185f11ae6a9-8857de58-a91b-4e05-95d0-91f01b7e91c6-000000","bounceType":"Permanent","bounceSubType":"General","bouncedRecipients":[{"emailAddress":"abcdxxx@refirio.net","action":"failed","status":"5.1.1","diagnosticCode":"smtp; 550 5.1.1 <abcdxxx@refirio.net>: Recipient address rejected: User unknown in relay recipient table"}],"timestamp":"2023-01-27T02:42:30.322Z","reportingMTA":"dns; e234-2.smtp-out.ap-northeast-1.amazonses.com"},"mail":{"timestamp":"2023-01-27T02:42:29.554Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185f11ae432-60aab4e8-b3a4-4f40-9b8b-886d027b3c50-000000","destination":["abcdxxx@refirio.net"],"headersTruncated":false,"headers":[{"name":"Received","value":"from refirio.net (ec2-3-113-235-47.ap-northeast-1.compute.amazonaws.com [3.113.235.47]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-XLR0CNL0M) id jWkq9bUZroC04PmhwDve for abcdxxx@refirio.net; Fri, 27 Jan 2023 02:42:29 +0000 (UTC)"},{"name":"Received","value":"from localhost (example.com [203.0.113.1]) by refirio.net (Postfix) with ESMTPA id 47471CAF15C for <abcdxxx@refirio.net>; Fri, 27 Jan 2023 11:42:29 +0900 (JST)"},{"name":"Date","value":"Fri, 27 Jan 2023 11:42:29 +0900"},{"name":"To","value":"メール受信者 <abcdxxx@refirio.net>"},{"name":"From","value":"メール送信者 <info@refirio.net>"},{"name":"Subject","value":"外部SMTPからのバウンスメールテスト"},{"name":"Message-ID","value":"<44c8337f6dbf9e4d37ce2fb7eedc0a41@localhost>"},{"name":"X-Mailer","value":"PHPMailer 5.2.19 (https://github.com/PHPMailer/PHPMailer)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Content-Transfer-Encoding","value":"base64"}],"commonHeaders":{"from":["\"メール送信者\" <info@refirio.net>"],"date":"Fri, 27 Jan 2023 11:42:29 +0900","to":["\"メール受信者\" <abcdxxx@refirio.net>"],"messageId":"01060185f11ae432-60aab4e8-b3a4-4f40-9b8b-886d027b3c50-000000","subject":"外部SMTPからのバウンスメールテスト"},"tags":{"ses:operation":["SendSmtpEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["3.113.235.47"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["cre-test-smtp-user.20220726"]}}} {"eventType":"Send","mail":{"timestamp":"2023-01-27T02:42:29.554Z","source":"info@refirio.net","sourceArn":"arn:aws:ses:ap-northeast-1:123456789012:identity/refirio.net","sendingAccountId":"123456789012","messageId":"01060185f11ae432-60aab4e8-b3a4-4f40-9b8b-886d027b3c50-000000","destination":["abcdxxx@refirio.net"],"headersTruncated":false,"headers":[{"name":"Received","value":"from refirio.net (ec2-3-113-235-47.ap-northeast-1.compute.amazonaws.com [3.113.235.47]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-XLR0CNL0M) id jWkq9bUZroC04PmhwDve for abcdxxx@refirio.net; Fri, 27 Jan 2023 02:42:29 +0000 (UTC)"},{"name":"Received","value":"from localhost (example.com [203.0.113.1]) by refirio.net (Postfix) with ESMTPA id 47471CAF15C for <abcdxxx@refirio.net>; Fri, 27 Jan 2023 11:42:29 +0900 (JST)"},{"name":"Date","value":"Fri, 27 Jan 2023 11:42:29 +0900"},{"name":"To","value":"メール受信者 <abcdxxx@refirio.net>"},{"name":"From","value":"メール送信者 <info@refirio.net>"},{"name":"Subject","value":"外部SMTPからのバウンスメールテスト"},{"name":"Message-ID","value":"<44c8337f6dbf9e4d37ce2fb7eedc0a41@localhost>"},{"name":"X-Mailer","value":"PHPMailer 5.2.19 (https://github.com/PHPMailer/PHPMailer)"},{"name":"MIME-Version","value":"1.0"},{"name":"Content-Type","value":"text/plain; charset=UTF-8"},{"name":"Content-Transfer-Encoding","value":"base64"}],"commonHeaders":{"from":["\"メール送信者\" <info@refirio.net>"],"date":"Fri, 27 Jan 2023 11:42:29 +0900","to":["\"メール受信者\" <abcdxxx@refirio.net>"],"messageId":"01060185f11ae432-60aab4e8-b3a4-4f40-9b8b-886d027b3c50-000000","subject":"外部SMTPからのバウンスメールテスト"},"tags":{"ses:operation":["SendSmtpEmail"],"ses:configuration-set":["refirio-ses-log"],"ses:source-ip":["3.113.235.47"],"ses:from-domain":["refirio.net"],"ses:caller-identity":["cre-test-smtp-user.20220726"]}},"send":{}}
EC2の /var/log/maillog には以下のとおり送信成功が記録されている SESへのリレー自体は成功しているから…だと思われる つまり送信ログからエラーを検知したければ、/var/log/maillog ではなくS3の方を調べる必要がある
Jan 27 11:42:29 ip-10-1-0-47 postfix/smtpd[3884]: connect from example.com[203.0.113.1] Jan 27 11:42:29 ip-10-1-0-47 postfix/smtpd[3884]: 47471CAF15C: client=example.com[203.0.113.1], sasl_method=LOGIN, sasl_username=info@refirio.net Jan 27 11:42:29 ip-10-1-0-47 postfix/cleanup[3888]: 47471CAF15C: message-id=<44c8337f6dbf9e4d37ce2fb7eedc0a41@localhost> Jan 27 11:42:29 ip-10-1-0-47 postfix/qmgr[3857]: 47471CAF15C: from=<info@refirio.net>, size=846, nrcpt=1 (queue active) Jan 27 11:42:29 ip-10-1-0-47 postfix/smtpd[3884]: disconnect from example.com[203.0.113.1] Jan 27 11:42:29 ip-10-1-0-47 postfix/smtp[3889]: Trusted TLS connection established to email-smtp.ap-northeast-1.amazonaws.com[203.0.113.2]:587: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits) Jan 27 11:42:29 ip-10-1-0-47 postfix/smtp[3889]: 47471CAF15C: to=<abcdxxx@refirio.net>, relay=email-smtp.ap-northeast-1.amazonaws.com[203.0.113.2]:587, delay=0.52, delays=0.12/0.01/0.13/0.27, dsn=2.0.0, status=sent (250 Ok 01060185f11ae432-60aab4e8-b3a4-4f40-9b8b-886d027b3c50-000000) Jan 27 11:42:29 ip-10-1-0-47 postfix/qmgr[3857]: 47471CAF15C: removed
なお、S3に格納される際のファイル名は、先に記載したとおり refirio-ses-log/ses-log-2023/01/26/06/refirio-ses-kinesis-1-2023-01-26-06-32-55-4459a487-45e3-41ad-80ca-d53999eeddc2 のような場所と名前になる 日付や時間が含まれているが、これはUTCの日時となっている(テストメールでなければ、ファイル内に日本時間が記録される) 特定の日付のメールを丸ごと取得するような場合、時差を考慮してデータを取得する必要があるので注意 ■プログラムからのメール送信ログ確認 一例だが、以下のようなPHPプログラムでログを表示できる SDKの導入については「AWS SDK(バージョン3)」を参照
<?php require 'vendor/autoload.php'; use Aws\S3\S3Client; use Aws\S3\Exception\S3Exception; define('AWS_KEY', 'XXXXX'); define('AWS_SECRET', 'YYYYY'); define('AWS_REGION', 'ap-northeast-1'); define('AWS_S3_BUCKET', 'refirio-ses-log'); define('AWS_S3_SES_PREFIX', 'ses-log-'); define('AWS_S3_SES_DATE', '2023/01/27'); $logs = []; try { // アクセスキーとシークレットアクセスキーを指定して接続 $client = new S3Client([ 'credentials' => [ 'key' => AWS_KEY, 'secret' => AWS_SECRET, ], 'region' => AWS_REGION, 'version' => 'latest', ]); // ディレクトリの一覧を取得 $result = $client->listObjects([ 'Bucket' => AWS_S3_BUCKET, 'Prefix' => AWS_S3_SES_PREFIX . AWS_S3_SES_DATE . '/', 'Delimiter' => '/', ]); $directories = []; foreach ($result['CommonPrefixes'] as $prefix) { $directories[] = $prefix['Prefix']; } // ファイルの一覧を取得 $files = []; foreach ($directories as $directory) { $result = $client->listObjects([ 'Bucket' => AWS_S3_BUCKET, 'Prefix' => $directory, 'Delimiter' => '/', ]); foreach ($result['Contents'] as $content) { $files[] = $content['Key']; } } // ログの内容を取得 foreach ($files as $file) { $result = $client->getObject([ 'Bucket' => AWS_S3_BUCKET, 'Key' => $file, ]); $lines = explode("\n", $result['Body']); foreach ($lines as $line) { if (empty($line)) { continue; } $logs[] = json_decode($line, true); } } } catch (S3Exception $e) { exit('S3Exception: ' . $e->getMessage()); } catch (Exception $e) { exit('Exception: ' . $e->getMessage()); } echo "<table border=\"1\">\n"; echo "<tr>\n"; echo "<th>eventType</td>\n"; echo "<th>timestamp</td>\n"; echo "<th>messageId</td>\n"; echo "<th>source</td>\n"; echo "<th>destination</td>\n"; echo "<th>headers From</td>\n"; echo "<th>headers To</td>\n"; echo "<th>headers Subject</td>\n"; echo "</tr>\n"; foreach ($logs as $data) { if ($data['eventType'] == 'Send') { continue; } $headers = []; foreach ($data['mail']['headers'] as $header) { $headers[$header['name']] = $header['value']; } echo "<tr>\n"; echo "<td>" . $data['eventType'] . "</td>\n"; echo "<td>" . date('Y-m-d H:i:s', strtotime($data['mail']['timestamp'])) . "</td>\n"; echo "<td>" . $data['mail']['messageId'] . "</td>\n"; echo "<td>" . $data['mail']['source'] . "</td>\n"; echo "<td>" . implode(', ', $data['mail']['destination']) . "</td>\n"; echo "<td>" . $headers['From'] . "</td>\n"; echo "<td>" . $headers['To'] . "</td>\n"; echo "<td>" . $headers['Subject'] . "</td>\n"; echo "</tr>\n"; } echo "</table>\n";
■バウンスメールの設定 別途バウンスメールの設定をしておくといい メールログからバウンスメールが発生したことを確認できたとしても、バウンスメールほどの情報量が無い 詳細は、このファイル内の「SES メール送信 > バウンスメールの設定」を参照 ■引き続き ログファイル名、ログファイルの内容とも9時間の時差がある(1月26日19時に送ったものが1月26日10時として記録された) 調整できるか

Advertisement