Skip to content

Commit 622b954

Browse files
authored
[FEAT] AWS SES 메일 발송 기능 구현 (#26)
1 parent b89a14b commit 622b954

File tree

5 files changed

+167
-1
lines changed

5 files changed

+167
-1
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@
6565
<version>6.0.2.RELEASE</version>
6666
</dependency>
6767

68+
<!-- aws ses -->
69+
<dependency>
70+
<groupId>com.amazonaws</groupId>
71+
<artifactId>aws-java-sdk-ses</artifactId>
72+
<version>1.11.227</version>
73+
</dependency>
74+
6875

6976
<!-- Spring -->
7077
<dependency>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.oya.kr.global.support;
2+
3+
import com.oya.kr.global.support.dto.request.SenderRequest;
4+
5+
/**
6+
* @author 김유빈
7+
* @since 2024.02.28
8+
*/
9+
public interface MailSender {
10+
11+
void send(SenderRequest request);
12+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.oya.kr.global.support;
2+
3+
import org.springframework.beans.factory.annotation.Qualifier;
4+
import org.springframework.beans.factory.annotation.Value;
5+
import org.springframework.stereotype.Component;
6+
7+
import com.amazonaws.auth.AWSStaticCredentialsProvider;
8+
import com.amazonaws.auth.BasicAWSCredentials;
9+
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
10+
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
11+
import com.oya.kr.global.support.dto.request.SenderRequest;
12+
13+
/**
14+
* @author 김유빈
15+
* @since 2024.02.28
16+
*/
17+
@Qualifier("SESSender")
18+
@Component
19+
public class SESSender implements MailSender {
20+
21+
private final String accessKey;
22+
private final String secretKey;
23+
private final String region;
24+
25+
public SESSender(
26+
@Value("${aws.ses.access-key}") String accessKey,
27+
@Value("${aws.ses.secret-key}") String secretKey,
28+
@Value("${aws.ses.region}") String region) {
29+
this.accessKey = accessKey;
30+
this.secretKey = secretKey;
31+
this.region = region;
32+
}
33+
34+
/**
35+
* AWS SES 를 이용하여 메일 발송
36+
*
37+
* @author 김유빈
38+
* @since 2024.02.28
39+
*/
40+
@Override
41+
public void send(SenderRequest request) {
42+
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
43+
AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder
44+
.standard()
45+
.withCredentials(new AWSStaticCredentialsProvider(credentials))
46+
.withRegion(region).build();
47+
client.sendEmail(request.toSendRequestDto());
48+
}
49+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.oya.kr.global.support.dto.request;
2+
3+
import java.util.List;
4+
5+
import com.amazonaws.services.simpleemail.model.Body;
6+
import com.amazonaws.services.simpleemail.model.Content;
7+
import com.amazonaws.services.simpleemail.model.Destination;
8+
import com.amazonaws.services.simpleemail.model.Message;
9+
import com.amazonaws.services.simpleemail.model.SendEmailRequest;
10+
11+
import lombok.Getter;
12+
import lombok.RequiredArgsConstructor;
13+
14+
/**
15+
* @author 김유빈
16+
* @since 2024.02.28
17+
*/
18+
@Getter
19+
@RequiredArgsConstructor
20+
public class SenderRequest {
21+
22+
private final String from;
23+
private final List<String> to;
24+
private final String subject;
25+
private final String content;
26+
27+
public SendEmailRequest toSendRequestDto() {
28+
Destination destination = new Destination()
29+
.withToAddresses(this.to);
30+
31+
Message message = new Message()
32+
.withSubject(createContent(this.subject))
33+
.withBody(new Body()
34+
.withHtml(createContent(this.content)));
35+
36+
return new SendEmailRequest()
37+
.withSource(this.from)
38+
.withDestination(destination)
39+
.withMessage(message);
40+
}
41+
42+
private Content createContent(String text) {
43+
return new Content()
44+
.withCharset("UTF-8")
45+
.withData(text);
46+
}
47+
}

src/main/java/com/oya/kr/popup/service/PlanService.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
import java.util.List;
55
import java.util.stream.Collectors;
66

7+
import org.springframework.beans.factory.annotation.Qualifier;
78
import org.springframework.stereotype.Service;
89
import org.springframework.transaction.annotation.Transactional;
910
import org.springframework.web.multipart.MultipartFile;
1011

12+
import com.oya.kr.global.support.MailSender;
1113
import com.oya.kr.global.support.StorageConnector;
14+
import com.oya.kr.global.support.dto.request.SenderRequest;
1215
import com.oya.kr.popup.controller.dto.request.PlanSaveRequest;
1316
import com.oya.kr.popup.controller.dto.response.AllPlanResponse;
1417
import com.oya.kr.popup.controller.dto.response.AllPlansResponse;
@@ -41,12 +44,23 @@
4144
*/
4245
@Service
4346
@Transactional
44-
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
4547
public class PlanService {
4648

4749
private final UserRepository userRepository;
4850
private final PlanRepository planRepository;
4951
private final StorageConnector s3Connector;
52+
private final MailSender sesSender;
53+
54+
public PlanService(
55+
UserRepository userRepository,
56+
PlanRepository planRepository,
57+
StorageConnector s3Connector,
58+
@Qualifier("SESSender") MailSender sesSender) {
59+
this.userRepository = userRepository;
60+
this.planRepository = planRepository;
61+
this.s3Connector = s3Connector;
62+
this.sesSender = sesSender;
63+
}
5064

5165
/**
5266
* 카테고리 리스트 조회 기능 구현
@@ -231,6 +245,19 @@ public void wait(String email, Long planId) {
231245
Plan savedPlan = planRepository.findById(planId, savedUser);
232246
savedPlan.waiting();
233247
planRepository.updateEntranceStatus(savedPlan);
248+
249+
String title = "[THEPOP] 제안해주신 사업계획서가 대기 상태로 전환되었습니다.";
250+
String content = String.format(
251+
"%s 고객님, 안녕하세요.\n"
252+
+ "제안해주신 사업계획서가 대기 상태로 전환되었습니다.\n"
253+
+ "대기 상태에는 커뮤니티 게시글을 자유롭게 작성하실 수 있습니다.\n"
254+
+ "이후 제안이 승인되면 팝업스토어 게시글을 올려 팝업스토어를 홍보하실 수 있습니다.\n"
255+
+ "팝업스토어 제안에 감사드립니다.\n"
256+
+ "THEPOP 드림", savedUser.getNickname());
257+
258+
SenderRequest request = new SenderRequest(
259+
savedUser.getEmail(), List.of(savedPlan.getUser().getEmail()), title, content);
260+
sesSender.send(request);
234261
}
235262

236263
/**
@@ -247,6 +274,18 @@ public void approve(String email, Long planId) {
247274
Plan savedPlan = planRepository.findById(planId, savedUser);
248275
savedPlan.approve();
249276
planRepository.updateEntranceStatus(savedPlan);
277+
278+
String title = "[THEPOP] 제안해주신 사업계획서가 승인되었습니다.";
279+
String content = String.format(
280+
"%s 고객님, 안녕하세요.\n"
281+
+ "팝업스토어 입점을 축하드립니다!\n"
282+
+ "사업계획서가 승인되어 팝업스토어 게시글을 올려 팝업스토어를 홍보하실 수 있습니다.\n"
283+
+ "팝업스토어 제안에 감사드립니다.\n"
284+
+ "THEPOP 드림", savedUser.getNickname());
285+
286+
SenderRequest request = new SenderRequest(
287+
savedUser.getEmail(), List.of(savedPlan.getUser().getEmail()), title, content);
288+
sesSender.send(request);
250289
}
251290

252291
/**
@@ -263,5 +302,17 @@ public void deny(String email, Long planId) {
263302
Plan savedPlan = planRepository.findById(planId, savedUser);
264303
savedPlan.deny();
265304
planRepository.updateEntranceStatus(savedPlan);
305+
306+
String title = "[THEPOP] 제안해주신 사업계획서가 거절되었습니다.";
307+
String content = String.format(
308+
"%s 고객님, 안녕하세요.\n"
309+
+ "안타깝지만 제안해주신 사업계획서는 현대백화점과 함께하지 못하게 되었습니다.\n"
310+
+ "이후에 더 좋은 사업계획서가 있다면 언제든 연락 바랍니다.\n"
311+
+ "팝업스토어 제안에 감사드립니다.\n"
312+
+ "THEPOP 드림", savedUser.getNickname());
313+
314+
SenderRequest request = new SenderRequest(
315+
savedUser.getEmail(), List.of(savedPlan.getUser().getEmail()), title, content);
316+
sesSender.send(request);
266317
}
267318
}

0 commit comments

Comments
 (0)