From 015e360d9e7cb58d027ab7e9e2fb8323e28d89c0 Mon Sep 17 00:00:00 2001 From: donghyunkim Date: Thu, 4 Apr 2024 21:04:18 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/demo/config/MailConfig.java | 43 +++++++++++++++++++ .../demo/controller/MailController.java | 30 +++++++++++++ .../com/example/demo/domain/EmailSender.java | 6 +++ .../example/demo/domain/EmailSenderImpl.java | 29 +++++++++++++ .../example/demo/domain/EmailTemplate.java | 18 ++++++++ .../example/demo/dto/EmailSendRequest.java | 20 +++++++++ .../demo/dto/EmailTemplateResponse.java | 12 ++++++ .../com/example/demo/service/MailService.java | 9 ++++ .../example/demo/service/MailServiceImpl.java | 39 +++++++++++++++++ .../demo/domain/EmailSenderImplTest.java | 18 ++++++++ 10 files changed, 224 insertions(+) create mode 100644 src/main/java/com/example/demo/config/MailConfig.java create mode 100644 src/main/java/com/example/demo/controller/MailController.java create mode 100644 src/main/java/com/example/demo/domain/EmailSender.java create mode 100644 src/main/java/com/example/demo/domain/EmailSenderImpl.java create mode 100644 src/main/java/com/example/demo/domain/EmailTemplate.java create mode 100644 src/main/java/com/example/demo/dto/EmailSendRequest.java create mode 100644 src/main/java/com/example/demo/dto/EmailTemplateResponse.java create mode 100644 src/main/java/com/example/demo/service/MailService.java create mode 100644 src/main/java/com/example/demo/service/MailServiceImpl.java create mode 100644 src/test/java/com/example/demo/domain/EmailSenderImplTest.java diff --git a/src/main/java/com/example/demo/config/MailConfig.java b/src/main/java/com/example/demo/config/MailConfig.java new file mode 100644 index 00000000..36ff9ba1 --- /dev/null +++ b/src/main/java/com/example/demo/config/MailConfig.java @@ -0,0 +1,43 @@ +package com.example.demo.config; + +import java.util.Properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +@Configuration +public class MailConfig { + + @Value("${spring.mail.host}") + private String host; + @Value("${spring.mail.port}") + private int port; + @Value("${spring.mail.username}") + private String username; + @Value("${spring.mail.password}") + private String password; + @Value("${spring.mail.properties.mail.smtp.auth}") + private String auth; + @Value("${spring.mail.properties.mail.smtp.starttls.enable}") + private String enable; + + @Bean + public JavaMailSender javaMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost(host); + mailSender.setPort(port); + mailSender.setUsername(username); + mailSender.setPassword(password); + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", auth); + props.put("mail.smtp.starttls.enable", enable); + props.put("mail.debug", "true"); + + return mailSender; + } +} diff --git a/src/main/java/com/example/demo/controller/MailController.java b/src/main/java/com/example/demo/controller/MailController.java new file mode 100644 index 00000000..f563c68a --- /dev/null +++ b/src/main/java/com/example/demo/controller/MailController.java @@ -0,0 +1,30 @@ +package com.example.demo.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; + +import com.example.demo.domain.auth.CafegoryTokenManager; +import com.example.demo.dto.EmailSendRequest; +import com.example.demo.dto.EmailTemplateResponse; +import com.example.demo.service.MailService; + +import lombok.RequiredArgsConstructor; + +@Controller +@RequiredArgsConstructor +public class MailController { + + private final CafegoryTokenManager cafegoryTokenManager; + private final MailService mailService; + + @PostMapping("/email") + public ResponseEntity sendEmail( + @RequestHeader("Authorization") String authorization, @RequestBody EmailSendRequest request) { + cafegoryTokenManager.getIdentityId(authorization); + EmailTemplateResponse response = mailService.sendEmail(request); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/com/example/demo/domain/EmailSender.java b/src/main/java/com/example/demo/domain/EmailSender.java new file mode 100644 index 00000000..a9b929c9 --- /dev/null +++ b/src/main/java/com/example/demo/domain/EmailSender.java @@ -0,0 +1,6 @@ +package com.example.demo.domain; + +public interface EmailSender { + + void sendSimpleMessage(String to, String subject, String text); +} diff --git a/src/main/java/com/example/demo/domain/EmailSenderImpl.java b/src/main/java/com/example/demo/domain/EmailSenderImpl.java new file mode 100644 index 00000000..505a7da3 --- /dev/null +++ b/src/main/java/com/example/demo/domain/EmailSenderImpl.java @@ -0,0 +1,29 @@ +package com.example.demo.domain; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; + +@Component +public class EmailSenderImpl implements EmailSender { + + @Autowired + private JavaMailSender mailSender; + + @Value("${mail.from}") + private String EMAIL_FROM; + + @Override + public void sendSimpleMessage(String to, String subject, String text) { + SimpleMailMessage message = new SimpleMailMessage(); + //setFrom에 들어가는 이메일 주소는 실제 발송 주소와 관련이 없다. + // Note that even though it’s not mandatory to provide the from address, many SMTP servers would reject such messages. + message.setFrom(EMAIL_FROM); + message.setTo(to); + message.setSubject(subject); + message.setText(text); + mailSender.send(message); + } +} diff --git a/src/main/java/com/example/demo/domain/EmailTemplate.java b/src/main/java/com/example/demo/domain/EmailTemplate.java new file mode 100644 index 00000000..5e8ac5dd --- /dev/null +++ b/src/main/java/com/example/demo/domain/EmailTemplate.java @@ -0,0 +1,18 @@ +package com.example.demo.domain; + +import lombok.Getter; + +@Getter +public enum EmailTemplate { + + STUDYONCE_LOCATION_CHANGED("[Cafegory] 카페 장소가 변경되었습니다.", "자세한 내용은 마이페이지를 확인 해 주세요."); + + EmailTemplate(String subject, String content) { + this.subject = subject; + this.content = content; + } + + private final String subject; + private final String content; + +} diff --git a/src/main/java/com/example/demo/dto/EmailSendRequest.java b/src/main/java/com/example/demo/dto/EmailSendRequest.java new file mode 100644 index 00000000..9ed5b08a --- /dev/null +++ b/src/main/java/com/example/demo/dto/EmailSendRequest.java @@ -0,0 +1,20 @@ +package com.example.demo.dto; + +import java.util.List; + +import lombok.Getter; + +@Getter +public class EmailSendRequest { + + private String messageType; + private List memberIds; + + public EmailSendRequest() { + } + + public EmailSendRequest(String messageType, List memberIds) { + this.messageType = messageType; + this.memberIds = memberIds; + } +} diff --git a/src/main/java/com/example/demo/dto/EmailTemplateResponse.java b/src/main/java/com/example/demo/dto/EmailTemplateResponse.java new file mode 100644 index 00000000..dc2ff3b0 --- /dev/null +++ b/src/main/java/com/example/demo/dto/EmailTemplateResponse.java @@ -0,0 +1,12 @@ +package com.example.demo.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class EmailTemplateResponse { + + private final String title; + private final String content; +} diff --git a/src/main/java/com/example/demo/service/MailService.java b/src/main/java/com/example/demo/service/MailService.java new file mode 100644 index 00000000..b9e0cd1b --- /dev/null +++ b/src/main/java/com/example/demo/service/MailService.java @@ -0,0 +1,9 @@ +package com.example.demo.service; + +import com.example.demo.dto.EmailSendRequest; +import com.example.demo.dto.EmailTemplateResponse; + +public interface MailService { + + EmailTemplateResponse sendEmail(EmailSendRequest request); +} diff --git a/src/main/java/com/example/demo/service/MailServiceImpl.java b/src/main/java/com/example/demo/service/MailServiceImpl.java new file mode 100644 index 00000000..5b9f9b83 --- /dev/null +++ b/src/main/java/com/example/demo/service/MailServiceImpl.java @@ -0,0 +1,39 @@ +package com.example.demo.service; + +import static com.example.demo.exception.ExceptionType.*; + +import org.springframework.stereotype.Service; + +import com.example.demo.domain.EmailSender; +import com.example.demo.domain.EmailTemplate; +import com.example.demo.domain.MemberImpl; +import com.example.demo.dto.EmailSendRequest; +import com.example.demo.dto.EmailTemplateResponse; +import com.example.demo.exception.CafegoryException; +import com.example.demo.repository.MemberRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MailServiceImpl implements MailService { + + private final EmailSender emailSender; + private final MemberRepository memberRepository; + + @Override + public EmailTemplateResponse sendEmail(EmailSendRequest request) { + EmailTemplate template = EmailTemplate.valueOf(request.getMessageType()); + for (Long memberId : request.getMemberIds()) { + emailSender.sendSimpleMessage(findMemberById(memberId).getEmail(), template.getSubject(), + template.getContent()); + } + return new EmailTemplateResponse(template.getSubject(), template.getContent()); + } + + private MemberImpl findMemberById(Long memberId) { + return memberRepository.findById(memberId) + .orElseThrow(() -> new CafegoryException(MEMBER_NOT_FOUND)); + } + +} diff --git a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java new file mode 100644 index 00000000..88f0d0db --- /dev/null +++ b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java @@ -0,0 +1,18 @@ +package com.example.demo.domain; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class EmailSenderImplTest { + + @Autowired + private EmailSender emailSender; + + @Test + void sendSimpleMessage() { + emailSender.sendSimpleMessage("ghffu405@gmail.com", "테스트 제목", "테스트 내용"); + } + +} \ No newline at end of file From 7a1ebe93a6cc29008028f83d6f0b99beba619b2c Mon Sep 17 00:00:00 2001 From: donghyunkim Date: Thu, 4 Apr 2024 21:41:32 +0900 Subject: [PATCH 2/6] =?UTF-8?q?env:=20build.gradle=20springboot=20starter?= =?UTF-8?q?=20mail=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 80677e15..9352a077 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,9 @@ dependencies { // jpa json 타입 implementation 'io.hypersistence:hypersistence-utils-hibernate-55:3.5.2' + + //spring boot starter mail + implementation 'org.springframework.boot:spring-boot-starter-mail' } tasks.named('test') { From 0fafdcef3d9e733e2f31d545d89c2ac944617759 Mon Sep 17 00:00:00 2001 From: donghyunkim Date: Thu, 4 Apr 2024 21:56:04 +0900 Subject: [PATCH 3/6] =?UTF-8?q?chore:=20checkstyle=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/demo/domain/EmailSenderImpl.java | 5 ++--- src/main/java/com/example/demo/service/MailServiceImpl.java | 1 - .../java/com/example/demo/domain/EmailSenderImplTest.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/demo/domain/EmailSenderImpl.java b/src/main/java/com/example/demo/domain/EmailSenderImpl.java index 505a7da3..9d8addde 100644 --- a/src/main/java/com/example/demo/domain/EmailSenderImpl.java +++ b/src/main/java/com/example/demo/domain/EmailSenderImpl.java @@ -13,14 +13,13 @@ public class EmailSenderImpl implements EmailSender { private JavaMailSender mailSender; @Value("${mail.from}") - private String EMAIL_FROM; + private String mailFrom; @Override public void sendSimpleMessage(String to, String subject, String text) { SimpleMailMessage message = new SimpleMailMessage(); //setFrom에 들어가는 이메일 주소는 실제 발송 주소와 관련이 없다. - // Note that even though it’s not mandatory to provide the from address, many SMTP servers would reject such messages. - message.setFrom(EMAIL_FROM); + message.setFrom(mailFrom); message.setTo(to); message.setSubject(subject); message.setText(text); diff --git a/src/main/java/com/example/demo/service/MailServiceImpl.java b/src/main/java/com/example/demo/service/MailServiceImpl.java index 5b9f9b83..e299eedd 100644 --- a/src/main/java/com/example/demo/service/MailServiceImpl.java +++ b/src/main/java/com/example/demo/service/MailServiceImpl.java @@ -35,5 +35,4 @@ private MemberImpl findMemberById(Long memberId) { return memberRepository.findById(memberId) .orElseThrow(() -> new CafegoryException(MEMBER_NOT_FOUND)); } - } diff --git a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java index 88f0d0db..24c50a8b 100644 --- a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java +++ b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java @@ -15,4 +15,4 @@ void sendSimpleMessage() { emailSender.sendSimpleMessage("ghffu405@gmail.com", "테스트 제목", "테스트 내용"); } -} \ No newline at end of file +} From 64cc5d15e76760321be666e89745a599e0faf2c4 Mon Sep 17 00:00:00 2001 From: donghyunkim Date: Thu, 4 Apr 2024 22:02:28 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=EC=8B=A4=EC=A0=9C=20api=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/demo/domain/EmailSenderImplTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java index 24c50a8b..d029f0cb 100644 --- a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java +++ b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java @@ -1,6 +1,5 @@ package com.example.demo.domain; -import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -10,9 +9,11 @@ class EmailSenderImplTest { @Autowired private EmailSender emailSender; + /* + 실제 api 호출 테스트 @Test void sendSimpleMessage() { emailSender.sendSimpleMessage("ghffu405@gmail.com", "테스트 제목", "테스트 내용"); } - + */ } From e9d73122ad2a4aaf50a8cf80baf6e1ca6c9e8727 Mon Sep 17 00:00:00 2001 From: donghyunkim Date: Thu, 4 Apr 2024 22:39:21 +0900 Subject: [PATCH 5/6] =?UTF-8?q?test:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo/domain/EmailSenderImplTest.java | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/test/java/com/example/demo/domain/EmailSenderImplTest.java diff --git a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java b/src/test/java/com/example/demo/domain/EmailSenderImplTest.java deleted file mode 100644 index d029f0cb..00000000 --- a/src/test/java/com/example/demo/domain/EmailSenderImplTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.example.demo.domain; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class EmailSenderImplTest { - - @Autowired - private EmailSender emailSender; - - /* - 실제 api 호출 테스트 - @Test - void sendSimpleMessage() { - emailSender.sendSimpleMessage("ghffu405@gmail.com", "테스트 제목", "테스트 내용"); - } - */ -} From 07a0883e23056b456228acd9b7242249a8dc36ee Mon Sep 17 00:00:00 2001 From: donghyunkim Date: Thu, 4 Apr 2024 22:40:38 +0900 Subject: [PATCH 6/6] =?UTF-8?q?env:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/resources/application.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index e896c76c..1ef8a4c2 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -12,6 +12,19 @@ spring: properties: hibernate: format_sql: true #이쁘게 해줌 + mail: + host: smtp.gmail.com + port: 587 + username: test-cafegory@gmail.com + password: test cafe gory pass + + properties: + mail: + smtp: + auth: true + starttls: + enable: true + logging: level: org.hibernate.SQL: trace #콘솔에 남기는게 아니라 로그로 남음. @@ -30,6 +43,8 @@ oauth: auth: https://nid.naver.com api: https://openapi.naver.com - jwt: secret: 01234567890123456789012345678901234567890123456789 + +mail: + from: cafegory@gmail.com