전자메일을 보내기 위한 프로토콜
인터넷에서 전자메일을 보내기 위해 가장 많이 사용되는 프로토콜 중 하나이다.
application.properties(yml)
에 적용해야 한다.#smtp 설정
spring.mail.host=smtp.naver.com // SMTP 서버명
spring.mail.port=465 // SMTP 포트번호
spring.mail.username=[서버메일주소]
spring.mail.password=[서버메일비밀번호]
spring.mail.properties.debug=true // 디버그모드 활성화
spring.mail.properties.mail.smtp.auth=true // SMTP 인증을 통해 메일 서버에 로그인 가능
spring.mail.properties.mail.smtp.ssl.enable= true //SSL 연결 사용
spring.mail.properties.mail.smtp.starttls.enable=true //SMTP STARTTLS 명령을 사용하여 암호화된 연결
spring.mail.properties.mail.smtp.ssl.trust=smtp.naver.com //메일 서버의 인증서를 신뢰할 수 있는 인증서로 등록
implementation 'org.springframework.boot:spring-boot-starter-mail'
MailForm
객체 형식으로 보낼 메시지를 작성한다.@Getter
@Setter
public class MailForm {
private String address;
private String title;
private String message;
}
PasswordUpdateForm
생성@Getter
@Setter
public class PasswordUpdateForm {
@NotEmpty(message = "기존 비밀번호는 필수항목입니다.")
String oldPassword;
@NotEmpty(message = "새로운 비밀번호는 필수항목입니다.")
String newPassword1;
@NotEmpty(message = "새로운 비밀번호 확인은 필수항목입니다.")
String newPassword2;
}
SiteUser
객체에 접근해야 하므로 findByEmail
메서드를 추가했다.Optional<SiteUser> findByEmail(String email);
createMailForm
createRandomPassword
메서드를 통해 랜덤 생성된 6자리 숫자를 임시 비밀번호로 지정updateTempPassword
를 통해 해당 계정의 비밀번호를 임시 비밀번호로 업데이트한다.MailForm
객체를 만들어 보낼 주소,제목,내용을 설정한다.updateTempPassword
passwordEncoder
를 통한 인코딩 필수!)updatePassword
updateTempPassword
와 동일createRandomPassword
Math.random()
을 통해 임의의 6자리 난수를 생성하여 리턴한다.sendEmail
MailForm
객체를 토대로 메시지를 생성한다.SimpleMailMessage
객체를 통해 다양한 메시지 내용 설정이 가능하다.JavaMailSender
객체(mailSender)를 통해 최종적으로 메일을 보낸다. public MailForm createMailForm(String email) {
String password = createRandomPassword();
updateTempPassword(password, email);
MailForm mailForm = new MailForm();
mailForm.setAddress(email);
mailForm.setTitle("임시비밀번호 안내 메일입니다.");
mailForm.setMessage("회원님의 임시 비밀번호는 " + password + "입니다. 감사합니다");
return mailForm;
}
public void updateTempPassword(String password, String email) {
SiteUser user = userRepository.findByEmail(email).get();
user.setPassword(passwordEncoder.encode(password));
}
public void updatePassword(String password, SiteUser user) {
user.setPassword(passwordEncoder.encode(password));
}
public String createRandomPassword() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6; i++) {
sb.append((int) (Math.random() * 10));
}
return sb.toString();
}
private final JavaMailSender mailSender; //@RequiredArgsConstructor를 통해 주입받음
public void sendEmail(MailForm mailForm) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(mailForm.getAddress());
message.setSubject(mailForm.getTitle());
message.setText(mailForm.getMessage());
message.setFrom("on8214@naver.com");
message.setReplyTo("on8214@naver.com");
mailSender.send(message);
}
/forgotPassword
/user/forgot_password
폼으로 이동@PreAuthorize
설정을 isAnonymous()
로 설정했다. (비밀번호 찾기는 로그인 없이 볼수 있어야하므로)/sendEmail
@RequestParam
을 통해 매개변수로 받는다.userService
의 createMailForm
에 이메일을 넣어 MailForm
객체를 반환받는다.userService
의 sendEmail
에 MailForm
객체를 넣어 최종적으로 메일 발신GET - /updatePassword
PasswordUpdateForm
을 매개변수로 넣어 비밀번호 변경 폼의 입력과 필드 매칭을 시킬 수 있다.POST - /updatePassword
@Validated
를 통해 PasswordUpdateForm
객체가 정상적으로 들어왔는지 확인BindingResult
객체에 에러가 담겼다면 비밀번호 변경 폼으로 다시 이동username
을 통해 유저 객체를 찾고 비밀번호 초기화 @PreAuthorize("isAnonymous()")
@GetMapping("/forgotPassword")
public String findPassword() {
return "/user/forgot_password";
}
@PreAuthorize("isAnonymous()")
@PostMapping("/sendEmail")
public String sendEmail(@RequestParam String email) {
MailForm mailForm = userService.createMailForm(email);
userService.sendEmail(mailForm);
return "redirect:/user/login";
}
@GetMapping("/updatePassword")
public String updatePassword(PasswordUpdateForm passwordUpdateForm) {
return "/user/update_password";
}
@PostMapping("/updatePassword")
public String updatePassword(@Validated PasswordUpdateForm passwordUpdateForm, BindingResult bindingResult, Principal principal) {
if (bindingResult.hasErrors()) {
return "/user/update_password";
}
if (!passwordUpdateForm.newPassword1.equals(passwordUpdateForm.newPassword2)) {
return "/user/update_password";
}
SiteUser user = userService.getUser(principal.getName());
userService.updatePassword(passwordUpdateForm.newPassword1, user);
return "redirect:/user/login";
}
UserController
와 UserService
에 너무 많은 역할이 생긴 느낌??