Skip to content

Commit 0cb0a63

Browse files
committed
feat: event 기반 비동기 이메일 전송 기능 구현
1 parent b6fd6b8 commit 0cb0a63

File tree

6 files changed

+127
-0
lines changed

6 files changed

+127
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.gdg.poppet.email.application.event;
2+
3+
import com.gdg.poppet.chat.domain.model.ChatRoom;
4+
import com.gdg.poppet.user.domain.model.User;
5+
import lombok.Getter;
6+
7+
@Getter
8+
public class EmailSendEvent {
9+
private final User user;
10+
private final ChatRoom chatRoom;
11+
12+
public EmailSendEvent(User user, ChatRoom chatRoom) {
13+
this.user = user;
14+
this.chatRoom = chatRoom;
15+
}
16+
}

src/main/java/com/gdg/poppet/email/application/service/EmailService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ public interface EmailService {
1616
List<EmailDto> postEmailAddress(String name, EmailRequestDto emailRequestDto);
1717
void patchEmailAddress(String name, Long emailId, EmailRequestDto emailRequestDto);
1818
void deleteEmailAddress(String name, Long emailId);
19+
20+
void sendEmail(String username);
1921
}

src/main/java/com/gdg/poppet/email/application/service/EmailServiceImpl.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.gdg.poppet.email.application.service;
22

3+
import com.gdg.poppet.chat.domain.model.ChatRoom;
4+
import com.gdg.poppet.chat.domain.repository.ChatRoomRepository;
5+
import com.gdg.poppet.email.application.event.EmailSendEvent;
6+
import com.gdg.poppet.email.infra.application.EmailSendService;
37
import com.gdg.poppet.global.exception.GlobalException;
48
import com.gdg.poppet.global.status.ErrorStatus;
59
import com.gdg.poppet.email.application.dto.request.EmailRequestDto;
@@ -11,18 +15,24 @@
1115
import com.gdg.poppet.email.domain.repository.EmailRepository;
1216
import com.gdg.poppet.user.domain.repository.UserRepository;
1317
import lombok.RequiredArgsConstructor;
18+
import lombok.extern.slf4j.Slf4j;
19+
import org.springframework.context.ApplicationEventPublisher;
1420
import org.springframework.stereotype.Service;
1521
import org.springframework.transaction.annotation.Transactional;
1622

1723
import java.util.List;
1824
import java.util.stream.Collectors;
1925

26+
@Slf4j
2027
@Service
2128
@RequiredArgsConstructor
2229
public class EmailServiceImpl implements EmailService {
2330

2431
private final UserRepository userRepository;
2532
private final EmailRepository emailRepository;
33+
private final ChatRoomRepository chatRoomRepository;
34+
private final EmailSendService emailSendService;
35+
private final ApplicationEventPublisher applicationEventPublisher;
2636

2737
/**
2838
* 사용자의 이메일 전송 주기를 반환한다.
@@ -131,6 +141,31 @@ public void deleteEmailAddress(String username, Long emailId) {
131141
emailRepository.delete(email);
132142
}
133143

144+
/**
145+
* 유저의 이메일 전송 주기에 따라, 주기 내에 생성된 이메일의 요약 내용을 이메일로 전송한다.
146+
*/
147+
@Transactional
148+
@Override
149+
public void sendEmail(String username) {
150+
// TODO: user data 얻는 과정 수정
151+
User user = getUser(username);
152+
153+
// 가장 최근 생성되고 메일을 보내지 않은 채팅방 조회
154+
List<ChatRoom> chatRooms = chatRoomRepository.findByUsernameAndCreatedAtAndIsMailSent(username);
155+
if (chatRooms.isEmpty()) return;
156+
157+
// 메일 보낼 채팅방 요약 내용 추출
158+
ChatRoom chatRoom = chatRooms.get(0);
159+
String chatSummary = chatRoom.getSummary();
160+
if (chatSummary == null) return;
161+
162+
// 메일 보냄 여부 수정
163+
chatRoom.updateIsMailSent();
164+
165+
// 메일 전송 이벤트 발행
166+
applicationEventPublisher.publishEvent(new EmailSendEvent(user, chatRoom));
167+
}
168+
134169
private void validateIsUserAuthorizedForEmail(User user, Email email) {
135170
if (!email.getUser().equals(user)) {
136171
throw new GlobalException(ErrorStatus.USER_EMAIL_FORBIDDEN);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.gdg.poppet.email.infra.application;
2+
3+
import com.gdg.poppet.email.application.event.EmailSendEvent;
4+
import com.gdg.poppet.email.domain.model.Email;
5+
import com.gdg.poppet.user.domain.model.User;
6+
import lombok.RequiredArgsConstructor;
7+
import lombok.extern.slf4j.Slf4j;
8+
import org.springframework.scheduling.annotation.Async;
9+
import org.springframework.stereotype.Component;
10+
import org.springframework.transaction.event.TransactionPhase;
11+
import org.springframework.transaction.event.TransactionalEventListener;
12+
13+
@Slf4j
14+
@Component
15+
@RequiredArgsConstructor
16+
public class EmailSendEventListener {
17+
18+
private final EmailSendService emailSendService;
19+
20+
@Async
21+
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
22+
public void handleEmailSendEvent(EmailSendEvent event) {
23+
User user = event.getUser();
24+
String summary = event.getChatRoom().getSummary();
25+
26+
for (Email email : user.getEmails()) {
27+
try {
28+
emailSendService.sendEmail(email.getEmailAddress(), summary);
29+
} catch (Exception e) {
30+
log.error("[*] {}으로 이메일 전송 중 오류 발생", email.getEmailAddress(), e);
31+
}
32+
}
33+
}
34+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.gdg.poppet.email.infra.application;
2+
3+
import jakarta.mail.MessagingException;
4+
import jakarta.mail.internet.MimeMessage;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.mail.javamail.JavaMailSender;
8+
import org.springframework.mail.javamail.MimeMessageHelper;
9+
import org.springframework.stereotype.Service;
10+
11+
@Slf4j
12+
@Service
13+
@RequiredArgsConstructor
14+
public class EmailSendService {
15+
16+
private final JavaMailSender mailSender;
17+
18+
public void sendEmail(String to, String body) throws MessagingException {
19+
MimeMessage mimeMessage = mailSender.createMimeMessage();
20+
21+
String subject = "POPPET";
22+
23+
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage);
24+
mimeMessageHelper.setTo(to);
25+
mimeMessageHelper.setSubject(subject);
26+
mimeMessageHelper.setText(body, true);
27+
28+
mailSender.send(mimeMessage);
29+
}
30+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.gdg.poppet.global.config;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
import org.springframework.scheduling.annotation.EnableAsync;
5+
6+
@Configuration
7+
@EnableAsync
8+
public class AsyncConfig {
9+
10+
}

0 commit comments

Comments
 (0)