Skip to content

Commit

Permalink
Merge pull request #26 from Likelion-YeungNam-Univ/feat/#2-user-email
Browse files Browse the repository at this point in the history
Feat/#2 user email
  • Loading branch information
jjjjjinseo authored Jul 28, 2024
2 parents a01496a + 0ccba04 commit 41528e5
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 7 deletions.
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ dependencies {
implementation 'com.google.oauth-client:google-oauth-client-jetty:1.23.0'
implementation 'com.google.apis:google-api-services-youtube:v3-rev20230816-2.0.0'
implementation 'com.google.http-client:google-http-client-jackson2:1.39.2'

//mail 인증
implementation 'org.springframework.boot:spring-boot-starter-mail'

//redis 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}

tasks.named('test') {
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/example/beginnerfitbe/email/EmailDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.beginnerfitbe.email;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class EmailDto {
private String email;
private String code;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.example.beginnerfitbe.email.config;

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;

import java.util.Properties;

@Configuration
public class EmailConfig {

@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 boolean auth;

@Value("${spring.mail.properties.mail.smtp.starttls.enable}")
private boolean starttlsEnable;

@Value("${spring.mail.properties.mail.smtp.starttls.required}")
private boolean starttlsRequired;

@Value("${spring.mail.properties.mail.smtp.connectiontimeout}")
private int connectionTimeout;

@Value("${spring.mail.properties.mail.smtp.timeout}")
private int timeout;

@Value("${spring.mail.properties.mail.smtp.writetimeout}")
private int writeTimeout;

@Bean
public JavaMailSender javaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host);
mailSender.setPort(port);
mailSender.setUsername(username);
mailSender.setPassword(password);
mailSender.setDefaultEncoding("UTF-8");
mailSender.setJavaMailProperties(getMailProperties());

return mailSender;
}

private Properties getMailProperties() {
Properties properties = new Properties();
properties.put("mail.smtp.auth", auth);
properties.put("mail.smtp.starttls.enable", starttlsEnable);
properties.put("mail.smtp.starttls.required", starttlsRequired);
properties.put("mail.smtp.connectiontimeout", connectionTimeout);
properties.put("mail.smtp.timeout", timeout);
properties.put("mail.smtp.writetimeout", writeTimeout);

return properties;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.beginnerfitbe.email.controller;

import com.example.beginnerfitbe.email.EmailDto;
import com.example.beginnerfitbe.email.service.EmailService;
import com.example.beginnerfitbe.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/auth")
public class EmailController {
private final EmailService emailService;
private final UserService userService;
@PostMapping("/email-send")
public ResponseEntity<?> emailSend(@RequestParam String email) throws Exception {
if(userService.emailCheck(email)){
return ResponseEntity.badRequest().body("이미 존재하는 회원입니다");
}
return ResponseEntity.ok(emailService.sendEmail(email));
}
@PostMapping("/email-verify")
public ResponseEntity<?> codeVerification(@RequestBody EmailDto emailDto){
return ResponseEntity.ok(emailService.codeVerification(emailDto));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.example.beginnerfitbe.email.service;

import java.util.Random;

import com.example.beginnerfitbe.email.EmailDto;
import com.example.beginnerfitbe.error.StateResponse;
import com.example.beginnerfitbe.redis.service.RedisService;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class EmailService {

private final JavaMailSender emailSender;
private final RedisService redisService;

@Value("${spring.mail.username}")
private String fromEmail;

private static final String ePw = createKey();

private MimeMessage createMessage(String to) throws Exception {
System.out.println("보내는 대상 : " + to);
System.out.println("인증 번호 : " + ePw);
MimeMessage message = emailSender.createMimeMessage();

message.addRecipients(MimeMessage.RecipientType.TO, to); // 보내는 대상
message.setSubject("beginner fit sign-up"); // 제목

String msgg = "";
msgg += "<div style='margin:20px;'>";
msgg += "<h1> !BEGINNERFIT! </h1>";
msgg += "<br>";
msgg += "<br>";
msgg += "<div align='center' style='border:1px solid black; font-family:verdana';>";
msgg += "<h3 style='color:black;'>회원가입 인증 코드입니다.</h3>";
msgg += "<div style='font-size:130%'>";
msgg += "CODE : <strong>";
msgg += ePw + "</strong><div><br/> ";
msgg += "</div>";
message.setText(msgg, "utf-8", "html"); // 내용
message.setFrom(new InternetAddress(fromEmail, "beginnerfit")); // 보내는 사람

return message;
}

public static String createKey() {
StringBuffer key = new StringBuffer();
Random rnd = new Random();

for (int i = 0; i < 8; i++) { // 인증코드 8자리
int index = rnd.nextInt(3); // 0~2 까지 랜덤

switch (index) {
case 0:
key.append((char) ((int) (rnd.nextInt(26)) + 97));
break;
case 1:
key.append((char) ((int) (rnd.nextInt(26)) + 65));
break;
case 2:
key.append((rnd.nextInt(10)));
break;
}
}
return key.toString();
}

public String sendEmail(String to) throws Exception {
MimeMessage message = createMessage(to);
try {
emailSender.send(message);
redisService.setDataExpire(ePw, to, 60 * 5L);
} catch (MailException es) {
es.printStackTrace();
throw new IllegalArgumentException();
}
return ePw;
}

public StateResponse codeVerification(EmailDto emailDto) {
String email = emailDto.getEmail();
String code = emailDto.getCode();

if (redisService.getData(code) != null && redisService.getData(code).equals(email)) {
return StateResponse.builder()
.code("SUCCESS")
.message("이메일 인증에 성공했습니다.")
.build();
}
return StateResponse.builder()
.code("FAIL")
.message("이메일 인증에 실패했습니다.")
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class SecurityConfig {
private static final String[] publicEndpoints = {
"/auth/sign-in",
"/auth/sign-up",
"auth/email-send",
"/auth/email-verify",
"/users/emailcheck",
"/users/health-info",
"/swagger-ui.html",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.beginnerfitbe.redis.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
public class RedisConfig {

@Value("${spring.data.redis.host}")
private String redisHost;

@Value("${spring.data.redis.port}")
private int redisPort;

@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(redisHost, redisPort);
}

@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory());
return template;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.example.beginnerfitbe.redis.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.Duration;

@Service
@RequiredArgsConstructor
public class RedisService {
private final StringRedisTemplate redisTemplate;

public String getData(String key){
ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
return valueOperations.get(key);
}
public void setData(String key,String value){
ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
valueOperations.set(key,value);
}
public void setDataExpire(String key,String value,long duration){
ValueOperations<String,String> valueOperations=redisTemplate.opsForValue();
Duration expireDuration= Duration.ofSeconds(duration);
valueOperations.set(key,value,expireDuration);
}
public void deleteData(String key){
redisTemplate.delete(key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,4 @@ public ResponseEntity<StateResponse> withdrawal(HttpServletRequest request) {
return userService.withdrawal(userId);
}

@GetMapping("/emailcheck")
@Operation(summary="이메일 중복 확인 메서드", description = "이메일을 받아 존재하는지 확인하는 메서드입니다.")
ResponseEntity<Boolean> emailCheck(@RequestParam(value = "email") String email){
return ResponseEntity.ok(userService.emailCheck(email));
}


}
22 changes: 22 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,28 @@ spring:
username: ${DATABASE_USER}
password: ${DATABASE_PASSWORD}

mail:
host: smtp.gmail.com
port: 587
username: ${EMAIL}
password: ${PASSWORD}
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
auth-code-expiration-millis: 1800000

data:
redis:
host: localhost
port: 6379

jwt:
secret: ${JWT_SECRET}
expiration: ${JWT_EXPIRATION}
Expand Down

0 comments on commit 41528e5

Please sign in to comment.