우선 이번 작업에서 주요 핵심내용은 아래와 같다.
1. REST API를 활용하여 이메일 템플릿 리스트 및 샘플메일 발송 기능 구현
2. JAVA SDK를 활용하여 기존 시스템에 적용
3. CORS 셋팅
내가 진행중인 프로젝트는 ADMIN과 API서버가 각각 별도로 존재하고 있다.
기존의 ADMIN에서는 API를 별도로 통신하지 않고 자체에서 CRUD기능을 controller에서 처리했기 때문에 이번에 작업을 하면서 API와 통신하기 위해서는 CORS셋팅이 필요했다. 그래서 이 부분을 먼저 어떻게 설정하는지 살펴보고 그 후에 SDK 연동부분을 살펴보도록 한다.
Spring Security 사용유무에 따라서 설정하는 방식은 다른 것으로 확인되었다. 여기서는 사용하고 있기때문에 이 부분과 관련되어 설정을 진행했다.
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.cors().configurationSource(corsConfigurationSource());
...
}
단 위와 같이 설정만 한다고 되는것은 아니고 CorsConfigurationSource 을 Bean으로 추가해줘야 함.
CorsConfigurationSource 작성 부분
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin(domainUrl);
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
Header와 Method를 사용하는 환경 기준에 따라서 설정해주면 되고 별다른 제한이 없으면 * 로 전체 허용한다.
compile group: 'com.amazonaws', name: 'aws-java-sdk-ses', version: '1.11.482'
기본적인 셋팅을 @Configuration로 작성한다.
@Configuration
@PropertySource("aws.properties")
public class AWSConfiguration {
@Value("${cloud.aws.credentials.accessKey}")
private String accessKey;
@Value("${cloud.aws.credentials.secretKey}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public BasicAWSCredentials basicAWSCredentials() {
return new BasicAWSCredentials(accessKey, secretKey);
}
@Bean
public AmazonS3Client amazonS3Client(AWSCredentials awsCredentials) {
AmazonS3Client amazonS3Client = new AmazonS3Client(awsCredentials);
amazonS3Client.setRegion(Region.getRegion(Regions.fromName(region)));
return amazonS3Client;
}
@Bean
public AmazonSimpleEmailService amazonSimpleEmailService() {
AWSStaticCredentialsProvider awsStaticCredentialsProvider = new AWSStaticCredentialsProvider(basicAWSCredentials());
return AmazonSimpleEmailServiceClientBuilder.standard()
.withCredentials(awsStaticCredentialsProvider)
.withRegion("ap-northeast-2")
.build();
}
}
createTemplate
Template template = new Template();
template.setTemplateName(templateName);
template.setSubjectPart(mailSubject);
template.setHtmlPart(templateHtml);
template.setTextPart(null);
CreateTemplateRequest request = new CreateTemplateRequest().withTemplate(template);
CreateTemplateResult result = amazonSimpleEmailService.createTemplate(request);
if (result.getSdkHttpMetadata().getHttpStatusCode() != 200) {
log.error("{}", result.getSdkResponseMetadata().toString());
}
updateTemplate
Template template = new Template();
template.setTemplateName(templateName);
template.setSubjectPart(mailSubject);
template.setHtmlPart(templateHtml);
template.setTextPart(null);
UpdateTemplateRequest request = new UpdateTemplateRequest().withTemplate(template);
UpdateTemplateResult result = amazonSimpleEmailService.updateTemplate(request);
if (result.getSdkHttpMetadata().getHttpStatusCode() != 200) {
log.error("{}", result.getSdkResponseMetadata().toString());
}
deleteTemplate
DeleteTemplateRequest request = new DeleteTemplateRequest().withTemplateName(templateName);
DeleteTemplateResult result = amazonSimpleEmailService.deleteTemplate(request);
if (result.getSdkHttpMetadata().getHttpStatusCode() != 200) {
log.error("{}", result.getSdkResponseMetadata().toString());
}
ListTemplate
public List<TemplateMetadata> list() {
ListTemplatesResult listTemplatesResult = amazonSimpleEmailService.listTemplates(new ListTemplatesRequest());
return listTemplatesResult.getTemplatesMetadata();
}
GetTemplate
public Template getTemplate(String templateName) {
GetTemplateResult templateResult = amazonSimpleEmailService.getTemplate(new GetTemplateRequest().withTemplateName(templateName));
return templateResult.getTemplate();
}
Email DTO
@Getter
public class AmazonMailDto {
public static final String fromEmail = "yourEamilDomain";
private final String to;
private final String templateName;
private final String templateData;
@Builder
public AmazonMailDto(String to, String templateName, String templateData) {
this.to = to;
this.templateName = templateName;
this.templateData = templateData;
}
public SendTemplatedEmailRequest sendTemplatedEmailRequest() {
Destination destination = new Destination().withToAddresses(this.to);
return new SendTemplatedEmailRequest()
.withDestination(destination)
.withSource(fromEmail)
.withTemplate(templateName)
.withTemplateData(templateData);
}
}
Send Email
여기서 templateData라는 변수가 존재하는데 이 부분은 메일에서 치환되는 값들을 보내기 위함이다. 그래서 보낼때는 Gson()을 활요하여 String으로 변환
public void send(String receiver, String templateName, Map<String, String> templateData) {
String templateDataJsonString = new Gson().toJson(templateData);
AmazonMailDto amazonMailDto = AmazonMailDto.builder()
.to(receiver)
.templateName(templateName)
.templateData(templateDataJsonString)
.build();
SendTemplatedEmailResult sendTemplatedEmailResult = amazonSimpleEmailService.sendTemplatedEmail(amazonMailDto.sendTemplatedEmailRequest());
sendResultCheck(sendTemplatedEmailResult);
}
위 작성한 코드로 실제 운영중인 서비스의 비즈니스 로직에 응용하여 적용을 했는데 문제없이 잘되는 것을 확인했다.
AWS에서 서버를 사용하고 있다면 SES의 기능은 사용하기 너무 좋은 기능이다. (서버 사용 시 일 50,000건까지 무료)