diff --git a/.gitignore b/.gitignore index 6a01ec8..81041f2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,7 @@ application-s3.properties # AWS Config 파일 AWSConfig.java -aws.yml \ No newline at end of file +aws.yml + +# 이메일 config +MailConfig.java \ No newline at end of file diff --git a/.gradle/6.7.1/executionHistory/executionHistory.bin b/.gradle/6.7.1/executionHistory/executionHistory.bin index 6e8cdef..b8068ef 100644 Binary files a/.gradle/6.7.1/executionHistory/executionHistory.bin and b/.gradle/6.7.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/6.7.1/executionHistory/executionHistory.lock b/.gradle/6.7.1/executionHistory/executionHistory.lock index 36cc223..f9b3947 100644 Binary files a/.gradle/6.7.1/executionHistory/executionHistory.lock and b/.gradle/6.7.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/6.7.1/fileHashes/fileHashes.bin b/.gradle/6.7.1/fileHashes/fileHashes.bin index fec873f..3de3139 100644 Binary files a/.gradle/6.7.1/fileHashes/fileHashes.bin and b/.gradle/6.7.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/6.7.1/fileHashes/fileHashes.lock b/.gradle/6.7.1/fileHashes/fileHashes.lock index 4c02e4d..5862a58 100644 Binary files a/.gradle/6.7.1/fileHashes/fileHashes.lock and b/.gradle/6.7.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/6.7.1/fileHashes/resourceHashesCache.bin b/.gradle/6.7.1/fileHashes/resourceHashesCache.bin index 0ce501d..5254bc5 100644 Binary files a/.gradle/6.7.1/fileHashes/resourceHashesCache.bin and b/.gradle/6.7.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/6.7.1/javaCompile/classAnalysis.bin b/.gradle/6.7.1/javaCompile/classAnalysis.bin index bef4d5c..af89fd7 100644 Binary files a/.gradle/6.7.1/javaCompile/classAnalysis.bin and b/.gradle/6.7.1/javaCompile/classAnalysis.bin differ diff --git a/.gradle/6.7.1/javaCompile/jarAnalysis.bin b/.gradle/6.7.1/javaCompile/jarAnalysis.bin index 666a697..4dfded5 100644 Binary files a/.gradle/6.7.1/javaCompile/jarAnalysis.bin and b/.gradle/6.7.1/javaCompile/jarAnalysis.bin differ diff --git a/.gradle/6.7.1/javaCompile/javaCompile.lock b/.gradle/6.7.1/javaCompile/javaCompile.lock index f8aadc9..82eeb4e 100644 Binary files a/.gradle/6.7.1/javaCompile/javaCompile.lock and b/.gradle/6.7.1/javaCompile/javaCompile.lock differ diff --git a/.gradle/6.7.1/javaCompile/taskHistory.bin b/.gradle/6.7.1/javaCompile/taskHistory.bin index e49d23e..9daedde 100644 Binary files a/.gradle/6.7.1/javaCompile/taskHistory.bin and b/.gradle/6.7.1/javaCompile/taskHistory.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 3e43535..6a1c31e 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/build.gradle b/build.gradle index b053209..2140e7c 100644 --- a/build.gradle +++ b/build.gradle @@ -59,7 +59,6 @@ dependencies { // 이메일 인증 implementation 'org.springframework.boot:spring-boot-starter-mail' implementation 'org.springframework.boot:spring-boot-starter-data-redis' - } test { diff --git a/build/tmp/compileJava/source-classes-mapping.txt b/build/tmp/compileJava/source-classes-mapping.txt index 53809b9..5f0b609 100644 --- a/build/tmp/compileJava/source-classes-mapping.txt +++ b/build/tmp/compileJava/source-classes-mapping.txt @@ -40,6 +40,8 @@ com/example/demo/src/main/model/GetEventsRes.java com.example.demo.src.main.model.GetEventsRes com/example/demo/src/user/model/PostUserRes.java com.example.demo.src.user.model.PostUserRes +com/example/demo/src/mail/model/PostVerifyCodeReq.java + com.example.demo.src.mail.model.PostVerifyCodeReq com/example/demo/src/category/model/GetCategoryDetailRes.java com.example.demo.src.category.model.GetCategoryDetailRes com/example/demo/src/main/model/GetEventDetailRes.java @@ -70,6 +72,8 @@ com/example/demo/src/store/model/GetTodaysDealMainRes.java com.example.demo.src.store.model.GetTodaysDealMainRes com/example/demo/src/store/model/PostScrapReq.java com.example.demo.src.store.model.PostScrapReq +com/example/demo/src/mail/service/MailService.java + com.example.demo.src.mail.service.MailService com/example/demo/src/user/model/GetHouseCategoryRes.java com.example.demo.src.user.model.GetHouseCategoryRes com/example/demo/src/store/model/GetInquiryRes.java @@ -122,6 +126,8 @@ com/example/demo/src/category/CategoryProvider.java com.example.demo.src.category.CategoryProvider com/example/demo/src/user/model/GetScrapFoldersRes.java com.example.demo.src.user.model.GetScrapFoldersRes +com/example/demo/src/mail/dao/MailDao.java + com.example.demo.src.mail.dao.MailDao com/example/demo/config/secret/Secret.java com.example.demo.config.secret.Secret com/example/demo/src/user/model/PostScrapBookRes.java @@ -148,12 +154,12 @@ com/example/demo/config/BaseException.java com.example.demo.config.BaseException com/example/demo/src/main/model/GetReviewWriteRes.java com.example.demo.src.main.model.GetReviewWriteRes -com/example/demo/src/review/model/GetMyReviewsRes.java - com.example.demo.src.review.model.GetMyReviewsRes com/example/demo/src/user/model/GetScrapHousePicRes.java com.example.demo.src.user.model.GetScrapHousePicRes com/example/demo/src/user/model/PostScrapBookReq.java com.example.demo.src.user.model.PostScrapBookReq +com/example/demo/src/review/model/GetMyReviewsRes.java + com.example.demo.src.review.model.GetMyReviewsRes com/example/demo/src/user/model/PostUserReq.java com.example.demo.src.user.model.PostUserReq com/example/demo/src/category/dao/CategoryDao.java @@ -166,6 +172,8 @@ com/example/demo/src/category/controller/CategoryController.java com.example.demo.src.category.controller.CategoryController com/example/demo/src/main/model/GetGuestOrderRes.java com.example.demo.src.main.model.GetGuestOrderRes +com/example/demo/src/mail/controller/MailController.java + com.example.demo.src.mail.controller.MailController com/example/demo/src/main/controller/MainController.java com.example.demo.src.main.controller.MainController com/example/demo/src/WebSecurityConfig.java @@ -174,6 +182,8 @@ com/example/demo/src/category/model/GetAllCategoryRes.java com.example.demo.src.category.model.GetAllCategoryRes com/example/demo/src/store/model/PostScrapRes.java com.example.demo.src.store.model.PostScrapRes +com/example/demo/config/mail/MailConfig.java + com.example.demo.config.mail.MailConfig com/example/demo/src/store/model/PostInquiryReq.java com.example.demo.src.store.model.PostInquiryReq com/example/demo/src/user/model/GetOrderReq.java diff --git a/src/main/java/com/example/demo/config/BaseResponseStatus.java b/src/main/java/com/example/demo/config/BaseResponseStatus.java index 5a8c8a6..3d27725 100644 --- a/src/main/java/com/example/demo/config/BaseResponseStatus.java +++ b/src/main/java/com/example/demo/config/BaseResponseStatus.java @@ -89,7 +89,9 @@ public enum BaseResponseStatus { EMPTY_INQUIRY_CATEGORY(false, 2055, "문의 카테고리를 입력해주세요."), EMPTY_INQUIRY_DESCRIPTION(false, 2056, "문의 내용을 입력해주세요."), INVALID_INQUIRY_ISPUBLIC(false, 2057, "공개 여부 코드가 잘못되었습니다. 0과 1 중에 다시 선택해주세요."), - + EMPTY_VERIFICATION_CODE(false, 2058, "인증 코드를 입력하세요."), + EMPTY_VERIFICATION_CODE_ID(false, 2059, "인증 코드 id를 입력해주세요."), + INVALID_VERIFICATION_CODE(false, 2060, "올바르지 않은 이메일 인증 코드이거나 만료된 인증 코드입니다."), /** * 3000 : Response 오류 */ diff --git a/src/main/java/com/example/demo/config/mail/MailConfig.java b/src/main/java/com/example/demo/config/mail/MailConfig.java new file mode 100644 index 0000000..01d9864 --- /dev/null +++ b/src/main/java/com/example/demo/config/mail/MailConfig.java @@ -0,0 +1,37 @@ +package com.example.demo.config.mail; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; + +@Configuration +public class MailConfig { + @Bean + public JavaMailSender javaMailService() { + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + + javaMailSender.setHost("smtp.naver.com"); + javaMailSender.setUsername("hongbeluga"); + javaMailSender.setPassword("leebfjds87x"); + + javaMailSender.setPort(465); + + javaMailSender.setJavaMailProperties(getMailProperties()); + + return javaMailSender; + } + + private Properties getMailProperties() { + Properties properties = new Properties(); + properties.setProperty("mail.transport.protocol", "smtp"); + properties.setProperty("mail.smtp.auth", "true"); + properties.setProperty("mail.smtp.starttls.enable", "true"); + properties.setProperty("mail.debug", "true"); + properties.setProperty("mail.smtp.ssl.trust","smtp.naver.com"); + properties.setProperty("mail.smtp.ssl.enable","true"); + return properties; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/src/mail/controller/MailController.java b/src/main/java/com/example/demo/src/mail/controller/MailController.java new file mode 100644 index 0000000..f4ae58b --- /dev/null +++ b/src/main/java/com/example/demo/src/mail/controller/MailController.java @@ -0,0 +1,76 @@ +package com.example.demo.src.mail.controller; + +import com.example.demo.config.BaseException; +import com.example.demo.config.BaseResponse; +import com.example.demo.config.BaseResponseStatus; +import com.example.demo.src.mail.model.PostVerifyCodeReq; +import com.example.demo.src.mail.service.MailService; +import com.example.demo.utils.ValidationRegex; +import jdk.nashorn.internal.parser.JSONParser; +import lombok.AllArgsConstructor; +import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/users/mails") +@AllArgsConstructor +public class MailController { + @Autowired + private final MailService mailService; + + + @ResponseBody + @PostMapping("") + public BaseResponse sendEmail(@RequestBody String data) throws BaseException{ + JSONObject parser = new JSONObject(data); + String email = parser.getString("email"); + + if(email == null){ + return new BaseResponse<>(BaseResponseStatus.POST_USERS_EMPTY_EMAIL); + } + + if(!ValidationRegex.isRegexEmail(email)){ + return new BaseResponse<>(BaseResponseStatus.POST_USERS_INVALID_EMAIL); + } + + try{ + + mailService.sendCertificationMail(email); + + long verifyCodeId = mailService.sendCertificationMail(email); + + return new BaseResponse(verifyCodeId); + } + catch (BaseException baseException){ + return new BaseResponse<>(baseException.getStatus()); + } + } + + @ResponseBody + @PostMapping("/verifications") + public BaseResponse verifyEmailCode(@RequestBody PostVerifyCodeReq postVerifyCodeReq) throws BaseException{ + if(postVerifyCodeReq.getCode() == null){ + return new BaseResponse<>(BaseResponseStatus.EMPTY_VERIFICATION_CODE); + } + + if(postVerifyCodeReq.getEmail() == null){ + return new BaseResponse<>(BaseResponseStatus.POST_USERS_EMPTY_EMAIL); + } + + try{ + int result = mailService.checkCode(postVerifyCodeReq); + + if(result == 0){ + return new BaseResponse<>(BaseResponseStatus.INVALID_VERIFICATION_CODE); + } + + String message = "이메일 인증에 성공하였습니다."; + + return new BaseResponse(message); + } + catch (BaseException baseException){ + return new BaseResponse<>(baseException.getStatus()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/src/mail/dao/MailDao.java b/src/main/java/com/example/demo/src/mail/dao/MailDao.java new file mode 100644 index 0000000..973598e --- /dev/null +++ b/src/main/java/com/example/demo/src/mail/dao/MailDao.java @@ -0,0 +1,41 @@ +package com.example.demo.src.mail.dao; + +import com.example.demo.src.mail.model.PostVerifyCodeReq; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; + +import javax.sql.DataSource; + +@Repository +public class MailDao { + private JdbcTemplate jdbcTemplate; + + @Autowired + public void setDataSource(DataSource dataSource){this.jdbcTemplate = new JdbcTemplate(dataSource);} + + public long createVerificationCode(String code, String email){ + String createVerificationCodeQuery = "INSERT INTO VerifyCodes(code, email) VALUES(?, ?);"; + Object[] createVerificationCodeQueryParams = new Object[]{code, email}; + + this.jdbcTemplate.update(createVerificationCodeQuery, createVerificationCodeQueryParams); + + String retrieveLastInsertIdQuery = "SELECT LAST_INSERT_ID();"; + + return this.jdbcTemplate.queryForObject(retrieveLastInsertIdQuery, long.class); + } + + public int checkCode(PostVerifyCodeReq postVerifyCodeReq){ + String checkCodeQuery = "SELECT EXISTS(\n" + + " SELECT codeId FROM VerifyCodes\n" + + " WHERE email = ? AND TIMESTAMPDIFF(SECOND , createdAt, CURRENT_TIMESTAMP) < 180\n" + + " AND code = ? AND codeId = ?\n" + + " );"; + Object[] checkCodeQueryParams = new Object[]{ + postVerifyCodeReq.getEmail(), postVerifyCodeReq.getCode(), postVerifyCodeReq.getId() + }; + + return this.jdbcTemplate.queryForObject(checkCodeQuery, int.class, checkCodeQueryParams); + } + +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/src/mail/model/PostVerifyCodeReq.java b/src/main/java/com/example/demo/src/mail/model/PostVerifyCodeReq.java new file mode 100644 index 0000000..f64ca8f --- /dev/null +++ b/src/main/java/com/example/demo/src/mail/model/PostVerifyCodeReq.java @@ -0,0 +1,14 @@ +package com.example.demo.src.mail.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class PostVerifyCodeReq { + String email; + String code; + long id; // verification Id +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/src/mail/service/MailService.java b/src/main/java/com/example/demo/src/mail/service/MailService.java index 2c813c9..0a45328 100644 --- a/src/main/java/com/example/demo/src/mail/service/MailService.java +++ b/src/main/java/com/example/demo/src/mail/service/MailService.java @@ -1,9 +1,83 @@ package com.example.demo.src.mail.service; +import com.example.demo.config.BaseException; +import com.example.demo.config.BaseResponseStatus; +import com.example.demo.config.secret.Secret; +import com.example.demo.src.mail.dao.MailDao; +import com.example.demo.src.mail.model.PostVerifyCodeReq; +import com.example.demo.src.user.UserProvider; import lombok.AllArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.MailException; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.mail.Message; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.UUID; @Service @AllArgsConstructor public class MailService { + + @Autowired + private final JavaMailSender javaMailSender; + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private final UserProvider userProvider; + + @Autowired + private final MailDao mailDao; + + public long sendCertificationMail(String email) throws BaseException { + if(userProvider.checkEmail(email) == 1){ + throw new BaseException(BaseResponseStatus.DUPLICATED_EMAIL); + } + try{ + String code = UUID.randomUUID().toString().substring(0, 6); + sendMail(code, email); + + return mailDao.createVerificationCode(code, email); + }catch (Exception exception){ + exception.printStackTrace(); + throw new BaseException(BaseResponseStatus.DATABASE_ERROR); + } + } + + public int checkCode(PostVerifyCodeReq postVerifyCodeReq) throws BaseException{ + try{ + return mailDao.checkCode(postVerifyCodeReq); + }catch (Exception exception){ + throw new BaseException(BaseResponseStatus.DATABASE_ERROR); + } + } + + private MimeMessage createMessage(String code, String email) throws Exception{ + MimeMessage message = javaMailSender.createMimeMessage(); + + message.addRecipients(Message.RecipientType.TO, email); + message.setSubject("오늘의 집 모의외주 프로젝트 인증 번호입니다."); + message.setText("이메일 인증코드: "+code); + + message.setFrom(new InternetAddress(Secret.RECIPIENT)); + + return message; + } + + public void sendMail(String code, String email) throws Exception{ + try{ + MimeMessage mimeMessage = createMessage(code, email); + javaMailSender.send(mimeMessage); + }catch (MailException mailException){ + mailException.printStackTrace(); + throw new IllegalAccessException(); + } + } + } \ No newline at end of file