お久しぶりです。
タイトルにもある通り、CDK で SES をやってみたので記事に残しておきます。
また、CDK で作って終わりだと寂しいので「SMTP でメールを送ってみた。」までやります。
必要なもの / 動作を確認している環境
- node
- v22.14.0
- cdk
- 2.1001.0 (build 130445d)
- aws-cli
- 1.38.8
- python
- 3.13.2
前提
- Route53 にホストゾーン設定済み
コード
Route53 にあるドメインに対して メール設定をしています。
そして、メール送信用の iam ユーザを作成しています。
※ これは SMTP のメール送信するときに使います。
import * as cdk from 'aws-cdk-lib';
import * as route53 from 'aws-cdk-lib/aws-route53';
import * as ses from 'aws-cdk-lib/aws-ses';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
export class AppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const PREFIX = "App";
const domainName = 'YOUR_DOMAIN_NAME'; // Route53 にホストゾーン
const mailDomainName = `mail.${domainName}`;
// Route53 を探索して HostedZone を取得
const hostedZoneId = route53.HostedZone.fromLookup(this, `${PREFIX}HostedZone`, {
domainName: domainName
});
// SES で 設定IDをつくる
const identity = new ses.EmailIdentity(this, `${PREFIX}EmailIdentity`, {
identity: ses.Identity.publicHostedZone(hostedZoneId),
mailFromDomain: mailDomainName
});
// DMARC レコードを作成
new route53.TxtRecord(this, `${PREFIX}DmarcRecord`, {
zone: hostedZoneId,
recordName: `_dmarc.${domainName}`,
values: [
`v=DMARC1; p=none; rua=mailto:dmarc@${mailDomainName}`
]
});
// iam
const smtpUser = new iam.User(this, `${PREFIX}SmtpUser`, {
userName: 'smtp-user', // smtp-user というユーザ名を作成
});
// ユーザにメール送信権限を付与
identity.grantSendEmail(smtpUser);
// smtp ユーザのアクセスキー情報の生成方法を出力
new cdk.CfnOutput(this, `${PREFIX}SmtpUserName`, {
value: `Run 'aws iam create-access-key --user-name ${smtpUser.userName}' to generate credentials.`,
});
}
}
デプロイ後
ses に色々とできています。
DMARC の設定もできているようです。
※ DMARC については この動画 がかなりわかりやすいです。
※ 今回の設定は DMARC レポートは受信しないです。
本番リクエストをする
外向きにメール送信するには、AWSさんから許可を得ないとできないです。
本番リクエスト
をしてAWSにお願いをします。
本番リクエストすると、AWSさんから使用目的を問いただされるので、答えてきます。
※ 仕事で数回本番リクエストしていますが、たまに使用目的を聞かれずにすぐに本番になる場合もありました。どういう振り分けかたかは不明。 🤔
このブログの問い合わせ窓口用にほしいともかけますが、
正直に技術的な調査をしたいという旨を連絡しました。
首を長くして待つこと1日。本番モードになりました。
これで 外向きにメールを送信できるようになります。🎉
SMTP経由でメールを送ってみる
ということで、SESで設定したメールアドレスを、SMTP経由でメールを送信してみます。
SMTP用のパスワード生成
SMTPメール送信用のパスワードを生成する必要があります。
このパスワード生成に CDK で作成した iam ユーザが必要になります。
※ 厳密に言うとメール送信できるポリシー( ses:SendEmail
と ses:SendRawEmail
)をがついているユーザがいれば良い。
これらの設定が面倒なので cdk でメール送信に必要なポリシーがついているユーザを作っています。
CDK を実行後に以下のアクセスキーを出力するコマンドを打てとターミナルに出力しています。
これを実行して、アクセスキーを生成します。
% cdk deploy
~~ # 略
# これ
Run 'aws iam create-access-key --user-name smtp-user' to generate credentials.
# 実行するとアクセスキーが生成される
% aws iam create-access-key --user-name smtp-user
{
"AccessKey": {
"UserName": "smtp-user",
"AccessKeyId": "**************",
"Status": "Active",
"SecretAccessKey": "****************",
"CreateDate": "2025-03-07T12:58:25Z"
}
}
あともうひと手間加える必要があり、SecretAccessKey から SMTP パスワードを生成します。
生成方法は AWS 様がのせている以下のコードを動かせばよいです。
% python main.py ${SMTP_USER_SECRET_ACCESS_KEY} ap-northeast-1
*********** # 出力された文字列が SMTP のアクセスキー
いざ送信
コードは typescript。
ネットの海に転がっているコードを参考にして作成しました。
import nodemailer from 'nodemailer';
const options = {
host: 'email-smtp.ap-northeast-1.amazonaws.com', // 東京リージョンで SES アカウントをつくったのでこれになる。SESの設定の中にホストがあるのでそれを確認すればよい。
port: 465,
secure: true,
auth: {
user: '*******', // smtp-user の AccessKey にある AccessKeyId
pass: '*********************' // SMTP パスワード
},
} as nodemailer.TransportOptions;
const mail = {
from: 'info@%{YOUR_DOMAIN}', // SES で作ったアドレス。ドメイン認証なので @ の前は何でも良い
to: 'TO_MAIL_ADDRESS', // 送信先
subject: 'Hello SES',
text: 'これはSESを使ったメール送信のテストです。',
html: '<div>これはSESを使ったメール送信のテストです。</div>'
} as nodemailer.SendMailOptions;
(async () => {
const transporter = nodemailer.createTransport(options);
await transporter.sendMail(mail);
console.log('Mail sent');
}
)();
コードの実行後、送信先のメールアドレスを見ると、メールを受信していることを確認できます。
メールの詳細をみると、DMARC の設定はバッチリです。
まとめ
CDK で SES を作りました。
そして、SMTPでメールを送信してみました。
ぜひ同じことをやろうとしている人は参考にしてみてください。
参考
