From 08352358ec00c39a2f140dc1fe37c1982b444f35 Mon Sep 17 00:00:00 2001
From: Jong1 <44349716+donsonioc2010@users.noreply.github.com>
Date: Tue, 19 Sep 2023 12:50:09 +0900
Subject: [PATCH] =?UTF-8?q?[feat]=20=EB=A9=94=EC=9D=BC=20=EB=B0=9C?=
=?UTF-8?q?=EC=86=A1=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=99=84?=
=?UTF-8?q?=EB=A3=8C=20(#33)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* chore : 메일 의존성 추가
* docs : Project Site Link 추가
* feat : 메일 기능 추가
* feat : 메일 기능 사용법 SampleCase 추가
* feat : 메일 위치 상수 클래스 생성
---
.../server/api/mail/MailPathConstants.java | 5 ++
.../server/api/mail/TestMailController.java | 39 ++++++++++
.../main/resources/templates/mail/sample.html | 16 +++++
Common/build.gradle | 3 +
.../common/exception/GlobalException.java | 11 +--
.../exception/IllegalArgumentException.java | 11 +++
.../common/exception/MailSendException.java | 11 +++
.../server/common/mail/SendMailUtil.java | 71 +++++++++++++++++++
.../src/main/resources/application-common.yml | 12 ++++
README.md | 6 +-
10 files changed, 178 insertions(+), 7 deletions(-)
create mode 100644 Api/src/main/java/picasso/server/api/mail/MailPathConstants.java
create mode 100644 Api/src/main/java/picasso/server/api/mail/TestMailController.java
create mode 100644 Api/src/main/resources/templates/mail/sample.html
create mode 100644 Common/src/main/java/picasso/server/common/exception/IllegalArgumentException.java
create mode 100644 Common/src/main/java/picasso/server/common/exception/MailSendException.java
create mode 100644 Common/src/main/java/picasso/server/common/mail/SendMailUtil.java
diff --git a/Api/src/main/java/picasso/server/api/mail/MailPathConstants.java b/Api/src/main/java/picasso/server/api/mail/MailPathConstants.java
new file mode 100644
index 00000000..1d106205
--- /dev/null
+++ b/Api/src/main/java/picasso/server/api/mail/MailPathConstants.java
@@ -0,0 +1,5 @@
+package picasso.server.api.mail;
+
+public class MailPathConstants {
+ public static String SAMPLE_MAIL = "mail/sample";
+}
diff --git a/Api/src/main/java/picasso/server/api/mail/TestMailController.java b/Api/src/main/java/picasso/server/api/mail/TestMailController.java
new file mode 100644
index 00000000..0134adc1
--- /dev/null
+++ b/Api/src/main/java/picasso/server/api/mail/TestMailController.java
@@ -0,0 +1,39 @@
+package picasso.server.api.mail;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import picasso.server.common.mail.SendMailUtil;
+
+import java.util.HashMap;
+
+/*
+ * TODO : 해당 컨트롤러 사용법 안내를 위한 TestController로 추후 삭제가 필요합니다.
+ */
+@Slf4j
+@RequestMapping("/mail")
+@RequiredArgsConstructor
+@RestController
+public class TestMailController {
+ private final SendMailUtil sendMailUtil;
+
+ /**
+ * @param mail 메일을 파라미터로 필요 id@mailHost
+ * @return
+ */
+ @GetMapping("/test")
+ public boolean testMail(@RequestParam("mail") String mail) {
+ return sendMailUtil.sendMail(
+ mail,
+ "테스트메일입니다.",
+ MailPathConstants.SAMPLE_MAIL,
+ new HashMap<>() {{
+ put("a", "A변수 데이터 입니다.");
+ put("b", "B변수 데이터 입니다.");
+ }});
+ }
+
+}
diff --git a/Api/src/main/resources/templates/mail/sample.html b/Api/src/main/resources/templates/mail/sample.html
new file mode 100644
index 00000000..75ab5604
--- /dev/null
+++ b/Api/src/main/resources/templates/mail/sample.html
@@ -0,0 +1,16 @@
+
+
+
+
+
테스트 SampleMail 입니다.
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Common/build.gradle b/Common/build.gradle
index 9e8e670a..5d73b364 100644
--- a/Common/build.gradle
+++ b/Common/build.gradle
@@ -7,6 +7,9 @@ dependencies {
api 'org.springframework.boot:spring-boot-starter-aop'
api 'org.springframework.boot:spring-boot-starter-validation'
+ // Mail
+ api 'org.springframework.boot:spring-boot-starter-mail'
+
//File
api 'commons-io:commons-io:2.13.0'
diff --git a/Common/src/main/java/picasso/server/common/exception/GlobalException.java b/Common/src/main/java/picasso/server/common/exception/GlobalException.java
index a407be1c..bc87e739 100644
--- a/Common/src/main/java/picasso/server/common/exception/GlobalException.java
+++ b/Common/src/main/java/picasso/server/common/exception/GlobalException.java
@@ -1,12 +1,12 @@
package picasso.server.common.exception;
-import static org.springframework.http.HttpStatus.BAD_REQUEST;
-import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
-
import lombok.AllArgsConstructor;
import lombok.Getter;
import picasso.server.common.dto.ErrorDetail;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+
@Getter
@AllArgsConstructor
public enum GlobalException implements BaseErrorCode {
@@ -16,8 +16,9 @@ public enum GlobalException implements BaseErrorCode {
DATE_FORMAT_ERROR(BAD_REQUEST.value(), "날짜 형식을 확인해주세요."),
FILE_UPLOAD_ERROR(INTERNAL_SERVER_ERROR.value(), "파일 업로드 중 오류가 발생하였습니다"),
FILE_DELETE_ERROR(INTERNAL_SERVER_ERROR.value(), "파일 삭제 중 오류가 발생하였습니다"),
- FILE_IO_ERROR(INTERNAL_SERVER_ERROR.value(), "파일 변환 중 오류가 발생하였습니다")
- ;
+ FILE_IO_ERROR(INTERNAL_SERVER_ERROR.value(), "파일 변환 중 오류가 발생하였습니다"),
+ ILLEGAL_ARGUMENT_ERROR(BAD_REQUEST.value(), "인자 값 문제로 인한 오류가 발생하였습니다"),
+ MAIL_SEND_ERROR(INTERNAL_SERVER_ERROR.value(), "메일 발송중 오류가 발생하였습니다");
private final Integer statusCode;
private final String reason;
diff --git a/Common/src/main/java/picasso/server/common/exception/IllegalArgumentException.java b/Common/src/main/java/picasso/server/common/exception/IllegalArgumentException.java
new file mode 100644
index 00000000..c3037d50
--- /dev/null
+++ b/Common/src/main/java/picasso/server/common/exception/IllegalArgumentException.java
@@ -0,0 +1,11 @@
+package picasso.server.common.exception;
+
+import static picasso.server.common.exception.GlobalException.ILLEGAL_ARGUMENT_ERROR;
+
+public class IllegalArgumentException extends BaseException {
+ public static final BaseException EXCEPTION = new IllegalArgumentException();
+
+ public IllegalArgumentException() {
+ super(ILLEGAL_ARGUMENT_ERROR);
+ }
+}
diff --git a/Common/src/main/java/picasso/server/common/exception/MailSendException.java b/Common/src/main/java/picasso/server/common/exception/MailSendException.java
new file mode 100644
index 00000000..2cc9c2ef
--- /dev/null
+++ b/Common/src/main/java/picasso/server/common/exception/MailSendException.java
@@ -0,0 +1,11 @@
+package picasso.server.common.exception;
+
+import static picasso.server.common.exception.GlobalException.MAIL_SEND_ERROR;
+
+public class MailSendException extends BaseException {
+ public static final MailSendException EXCEPTION = new MailSendException();
+
+ public MailSendException() {
+ super(MAIL_SEND_ERROR);
+ }
+}
diff --git a/Common/src/main/java/picasso/server/common/mail/SendMailUtil.java b/Common/src/main/java/picasso/server/common/mail/SendMailUtil.java
new file mode 100644
index 00000000..4d97aa74
--- /dev/null
+++ b/Common/src/main/java/picasso/server/common/mail/SendMailUtil.java
@@ -0,0 +1,71 @@
+package picasso.server.common.mail;
+
+import jakarta.mail.Message;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.MimeMessage;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Component;
+import org.thymeleaf.context.Context;
+import org.thymeleaf.spring6.SpringTemplateEngine;
+import picasso.server.common.exception.IllegalArgumentException;
+import picasso.server.common.exception.MailSendException;
+
+import java.util.Map;
+
+import static org.apache.commons.codec.CharEncoding.UTF_8;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class SendMailUtil {
+ private final JavaMailSender javaMailSender;
+ private final SpringTemplateEngine templateEngine;
+
+
+ /**
+ * Key는 현재 Mail에 사용중인 변수를, Value는 해당 메일 페이지에 들어갈 값을 입력하면 됩니다.
+ *
+ * @param toUser 발송자 메일
+ * @param title 메일 제목
+ * @param pagePath ThymeLeaf(HTML)파일 경로
+ * @param content ThymeLeaf에 들어갈 변수 Map (Not Null!!!)
+ * @return
+ */
+ public boolean sendMail(String toUser, String title, String pagePath, Map content) {
+ try {
+ parameterValidate(toUser, title, content);
+ MimeMessage message = javaMailSender.createMimeMessage();
+ message.addRecipients(Message.RecipientType.TO, toUser);
+ message.setSubject(title, UTF_8);
+ message.setText(getContent(pagePath, content), UTF_8, "html");
+ javaMailSender.send(message);
+ log.info("[SendMail Success] ToUser >>> {}, Title >>> {}, PagePath >>> {}", toUser, title, pagePath);
+ return true;
+ } catch (MessagingException e) {
+ log.error("[SendMail Failed] Exception Reason >>> MessageException, ToUser >>> {}, Title >>> {}, PagePath >>> {}", toUser, title, pagePath);
+ throw MailSendException.EXCEPTION;
+ } catch (Exception e) {
+ log.error("[SendMail Failed] Exception Reason >>> {}, ToUser >>> {}, Title >>> {}, PagePath >>> {}", e.getClass(), toUser, title, pagePath);
+ throw MailSendException.EXCEPTION;
+ }
+ }
+
+
+ //Valid, NotNull를 쓸까했는데... 안먹는걸로 기억이나서..
+ private void parameterValidate(String toUser, String title, Map content) {
+ if (toUser == null || title == null || content == null ||
+ title.isEmpty() || toUser.isEmpty()) {
+ throw IllegalArgumentException.EXCEPTION;
+ }
+ }
+
+ // html파일에서 메일내용을 가져옴
+ private String getContent(String pagePath, Map content) {
+ Context context = new Context();
+ content.forEach(context::setVariable);
+ return templateEngine.process(pagePath, context);
+ }
+
+}
diff --git a/Common/src/main/resources/application-common.yml b/Common/src/main/resources/application-common.yml
index 761cc112..08c204eb 100644
--- a/Common/src/main/resources/application-common.yml
+++ b/Common/src/main/resources/application-common.yml
@@ -4,6 +4,18 @@ naver:
region-name: kr-standard
bucket-name: picasso-bucket
+
+spring:
+ mail:
+ host: smtp.gmail.com
+ port: 587
+ properties:
+ mail:
+ smtp:
+ auth: true
+ starttls:
+ enable: true
+
---
spring:
config:
diff --git a/README.md b/README.md
index 1efd92b7..db908d22 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
-# Picasso
-[![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fdonsonioc2010%2Fpicasso&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com)
+# Picasso
+[홈페이지 링크](http://picasso.jong1.com/) [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fdonsonioc2010%2Fpicasso&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com)
+
+---
## 주제
> [!NOTE]
> 미술품 경매 사이트