AWS SES Terraform SpringBoot メール送信 実装 サンプル

今回は、AWSのSESをメールサーバーとして、
SpringBootのAPIからメールを送信する実装メモとなります。

独自ドメインは使用せずに自分の所有しているメールアドレスを利用します。
AWS SESは、サンドボックスモードで動作させます。
※サンドボックスモードでも無料枠に当てはまらない場合、通常と同様に料金が発生します。

AWS SESの設定は、Terraformで簡単に設定してみます。

参考

AWS SDK を使用して Amazon SES 経由で E メールを送信する
Initialize Terraform configuration
AWS SES pricing


AWS SES設定

・tfファイル作成

以下の内容でtfファイルを作成します。

こちらで設定したメールアドレスが、メール送信処理の送信元となります。
有効なメールアドレスを設定する必要があります。

また、後述のメールアドレスが有効であることの確認(検証)が行われるまでメール送信を行えません。

provider "aws" {
  region = "us-east-1" # 動作させるリージョンを指定
}

resource "aws_ses_email_identity" "send_ses_mail_example" {
  email = "your-email@example.com" # 設定したいメールアドレス
}

・Terraform実行

tfファイルが存在するディレクトリで、
以下のコマンドを順に実行してSES側を設定します。

terraform init # 初期化
terraform plan # インフラ設定確認
terraform apply # インフラ設定適応

Terraform AWS SES init

Terraform AWS SES plan

Terraform AWS SES apply

メールアドレス検証

Terraformコマンドを実行してSES設定を行ったら、
設定したメールアドレスの検証を実施して、メール送信できる様にします。

SESに設定された時点で、該当のメールアドレス宛に、
以下の様な検証用メールが届きます。こちらのメールより検証を完了させます。

AWS SES verification Request mail

検証を確定すると以下の画面に遷移します。

AWS SES verification Request Done    SES上の画面でも該当のメールアドレスのIDステータスが、検証済みに変化します。

AWS SES verification Request done


メール送信処理実装

SESの設定が完了したら、簡単なメール送信処理を実装して、
メールが送信されることを確認します。

・Gradle設定


plugins {
    id 'java'
    id 'org.springframework.boot' version '3.4.1'
    id 'io.spring.dependency-management' version '1.1.7'
}

group = 'example.com'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-mail'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation platform('software.amazon.awssdk:bom:2.27.21')
    implementation 'software.amazon.awssdk:ses'
    implementation 'software.amazon.awssdk:regions'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
    useJUnitPlatform()
}

・テスト用コントローラクラス

import example.com.springbootmailses.service.SesEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SendMailController {

    @Autowired
    private SesEmailService sesEmailService;

    @GetMapping("/sendTestMail")
    public String sendTestMailSes() {
        String from = "your-email@example.com"; // 検証済みのメールアドレスを指定する
        String to = "to@test.com"; // 宛先のメールアドレスを指定する
        String subject = "This is a test email. SES mail"; // メールタイトル
        String body = "This is a test email body. SES mail"; // メール本文 
        return sesEmailService.sendEmail(from, to, subject, body);
    }
}

・テスト用サービスクラス


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ses.SesClient;
import software.amazon.awssdk.services.ses.model.*;

import java.net.URI;

@Service
public class SesEmailService {

    @Value("${aws.ses.endpoint}")
    private String sesEndpoint;

    @Value("${aws.region}")
    private String region;

    private final TemplateEngine templateEngine;

    public SesEmailService(TemplateEngine templateEngine) {
        this.templateEngine = templateEngine;
    }

    public String sendEmail(String from, String to, String subject, String body) {
        // Create a new SES client
        try (final SesClient sesClient = SesClient.builder()
                .endpointOverride(URI.create(sesEndpoint))
                .region(Region.of(region))
                .build()) {

            // Create the email request
            final Context context = new Context();
            context.setVariable("body", body);
            // set other variables as needed for the template
            final String htmlBody = templateEngine.process("emailTemplate", context);

            // Create the email request
            final SendEmailRequest emailRequest = SendEmailRequest.builder()
                    .source(from) // 送信元設定
                    .destination(Destination.builder()
                            .toAddresses(to) // 宛先設定
                            .build())
                    .message(Message.builder()
                            .subject(Content.builder()
                                    .data(subject) // 件名設定
                                    .build())
                            .body(Body.builder()
                                    .html(Content.builder()
                                            .data(htmlBody) // HTML本文設定
                                            .build())
                                    .build())
                            .build())
                    .build();

            try {
                // Send the email
                sesClient.sendEmail(emailRequest);
            } catch (SesException e) {
                e.printStackTrace();
                return "Failed to send email.";
            }
        }
        return "Email sent successfully.";
    }
}

SESエンドポイント、リージョン設定

SESのエンドポイントとリージョンの設定を定義します。
以下は、propertiesファイルの例です。

aws.ses.endpoint=https://email.us-east-1.amazonaws.com
aws.region=us-east-1

・メールテンプレート

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Email Template</title>
</head>
<body>
<p th:text="${body}"></p>
</body>
</html>

テスト実行してみます。

AWS SES sample

宛先のメールボックスを確認するとメールが届いています。
※迷惑メールボックス等に振り分けられる可能性があります。

AWS SES sample

 


今回のメモは以上となります。
現時点ではAWSのサービス(EC2)からメール送信を行う場合などで、
無料枠も有りますので是非チェックしてみて下さい。

https://aws.amazon.com/jp/ses/pricing/

都内でエンジニアをやっています。 2017年に脱サラ(法人設立)しました。 仕事で調べたことや、気になったことをメモしています。
投稿を作成しました 178

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連投稿

検索語を上に入力し、 Enter キーを押して検索します。キャンセルするには ESC を押してください。

トップに戻る