Back to tech

CDK で SES を作って SMTP でメールを送信するまで

3 min read
Table of Contents

お久しぶりです。

タイトルにもある通り、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:SendEmailses: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 様がのせている以下のコードを動かせばよいです。

docs.aws.amazon.com
docs.aws.amazon.com
% 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でメールを送信してみました。

ぜひ同じことをやろうとしている人は参考にしてみてください。

参考

AWS CDKでSPF、DKIM、DMARC設定をしたAmazon SES を作成する - Qiita
qiita.com
image