11. SpringBoot에서 Amazon SES 서비스 사용하기

SpringBoot에서 Amazon SES 서비스 사용하기

2019-12-01 기준 동작 성공

AWS를 이용한 App을 만들기 위해 작업을 하다가 메일 인증을 진행해야 되서 SES 서비스를 사용해 보려고 했다.

1. SES 란?

Amazon Simple Email Service를 말하며 OutBound만 가능한 이메일 서비스다.

예를 들어, 특별 행사 안내 등의 마케팅 이메일, 주문 확인서 등의 거래 이메일, 뉴스레터 등의 기타 통신문을 발송할 수 있습니다. Amazon SES를 사용하여 메일을 수신하면 이메일 자동 응답기, 이메일 구독 해제 시스템, 수신 이메일에서 고객 지원 티켓을 생성하는 애플리케이션과 같은 소프트웨어 솔루션을 개발할 수 있습니다.

자세한 사항은 AWS SES에서 알아보길 바란다.

1-1. 사용하기 이전 사전 작업!! (중요)

SES는 아웃바운드만 지원을 한다. 그렇기에 사용자가 미리 이전에 작업을 해야될 부분이 존재한다. SES는 두가지로 Identity Management를 지원하는데 1) domain 2) email address(다른 이메일) 이렇게 두가지 이다.

여기서 1번에 대해서는 부록으로 기록하고 일단 2번의 경우로 진행하겠다. (아직 진행과정에서 문제가 있어 부록으로 뺍니다.)

  1. 이메일에 대해 'Verify a new Email Address' 버튼을 클릭하여 본인의 이메일을 등록한다.

  2. 여기를 눌러 API를 사용하기위해 Security Credential 을 발급받는다.

  3. 발급 과정 3번째 위치해 있는 Access Keys (Access key ID and secret access key) 를 눌러 "Create New Access Key"를 클릭합니다. 키를 다운로드 받고 잘 저장해 둡니다. => 해당키는 다른데에서도 인증에 쓰일 수 있으니 보관 꼭!!

    key를 다운로드 받으면 csv 파일인데 vi 명령어로 열어보면

          AWSAccessKeyId = AKIA*******Q*******
          AWSSecretKey = DUo1********************gW5***

    같이 보입니다. 이 키를 (~/.aws/credentials)에 맞게 저장합니다. => 본인의 경우 EC2와 함께 사용해서 자동배포를 시킬거라 따로 저장을 하지 않고 진행했습니다. (밑에서 확인!)

2. SES를 사용하기 위해 추가해야 할 dependency

인터넷에 보면 많은 예시들이 있긴하지만 2019년에 들어 따라해본 결과 업데이트 됨에 따라 credential 인증 부분에 문제가 있었다. 따라서 본인이 수행해본 결과대로 작성을 하겠다.

        <!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-ses -->
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-ses</artifactId>
            <version>1.11.227</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/software.amazon.awssdk/ses -->
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>ses</artifactId>
            <version>2.10.25</version>
        </dependency>

3. SenderDto 만들기

@Getter
public class SenderDto {
    private String from;
    private List<String> to = new ArrayList<>();
    private String subject;
    private String content;

    @Builder
    public SenderDto(String from, List<String> to, String subject, String content) {
        this.from = from;
        this.to = to;
        this.subject = subject;
        this.content = content;
    }

    public void addTo(String email){
        this.to.add(email);
    }

    public SendEmailRequest toSendRequestDto(){
        Destination destination = new Destination()
                .withToAddresses(this.to);

        Message message = new Message()
                .withSubject(createContent(this.subject))
                .withBody(new Body()
                        .withHtml(createContent(this.content))); // content body는 HTML 형식으로 보내기 때문에 withHtml을 사용합니다.

        return new SendEmailRequest()
                .withSource(this.from)
                .withDestination(destination)
                .withMessage(message);
    }

    private Content createContent(String text) {
        return new Content()
                .withCharset("UTF-8")
                .withData(text);
    }
}

4. Sender 만들기

@Slf4j
public class Sender {
//  @Value로도 받을 수 있습니다. 인터넷에 찾아보세요! 
//      @Value("${AWSAccessKeyId}")
//      private String AWS_ACCESS_KEY_ID;
//
//      @Value("${AWSSecretKey}")
//      private String AWS_SECRET_KEY;

    public void send(SenderDto senderDto){
        try {
            log.info("Attempting to send an email through Amazon SES by using the AWS SDK for Java...");
            // 아래 부분에 위에서 받은 ID, Key를 집어 넣습니다.
            // 인증방식은 제가 고쳐서 진행했습니다.
            BasicAWSCredentials awsCreds = new BasicAWSCredentials("AKIA*******Q*******","DUo1********************gW5***");
            AWSStaticCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(awsCreds);
            try {
                // 아래와 같이 인증방식을 변경함.
                credentialsProvider.getCredentials();
            } catch (Exception e) {
                throw new AmazonClientException(
                        "Cannot load the credentials from the credential profiles file. " +
                                "Please make sure that your credentials file is at the correct " +
                                "location (~/.aws/credentials), and is in valid format.",
                        e);
            }

            AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
                    .withCredentials(credentialsProvider)
                    // 자신이 설정한 리전으로 변경할 것!!
                    .withRegion("us-east-1")
                    .build();

            // Send the email.
            client.sendEmail(senderDto.toSendRequestDto());
            log.info("Email sent!");

        } catch (Exception ex) {
            log.error("The email was not sent.");
            log.error("Error message: " + ex.getMessage());
            throw new AmazonClientException(
                    ex.getMessage(),
                    ex);
        }
    }
}

5. Test Case 만들어 실행해보기

@RunWith(SpringRunner.class)
@SpringBootTest(classes= AttendenceAppApplication.class)
public class emailTest {
    @Test
    public void sendMail() {
        Sender sender = new Sender();
        SenderDto dto = new SenderDto("djunnni@gmail.com",Lists.newArrayList("djunnni@gmail.com"), "테스트", "안녕하세요");

        sender.send(dto);
    }
}

결과는 재대로 이메일이 전송되었음을 확인 할 수 있습니다.

하지만!! 여기서 문제점이 있습니다. 바로 SES는 초기에 200건 까지는 내부 인증 고객에게만 제공하는 규칙이 설정되어있습니다. 내부고객에게만 제공하는 규칙을 => 아무에게나 보낼 수 있도록 변경해야 됩니다.

이 방법에 대해서는 "1. sand box 해제하기" 를 아래에서 읽어주세요.

AWS SES (Simple Email Service) Spring Boot 프로젝트에서 사용하기를 참고해서 진행해 주세요.

저도 위에 분의 코드를 따라하다가 credential 부븐에서 제가 자체로 수정을 하였습니다. => 고친이유 : EC2로 자동배포를 할 예정이여서 .aws/credential을 넣을 필요없이 바로 static하게 넣어서 사용했음.

** 부록에서는 thymleaf의 양식으로 메일로 보내는 코드를 작성해보고 위에서 말씀드린 도메인을 이용한 메일보내기를 해보도록 하겠습니다.

Last updated