메일을 보내기 위한 로직 작성
UserService 에서 추가
private final JavaMailSender javaMailSender;
private final SpringTemplateEngine springTemplateEngine;
option+enter로 Add contructor parameter하여 @Autowired에 추가
스프링에서 제공하는 웹 어플리케이션에서 메일을 보다 손쉽게 보낼 수 있도록 해주는 API
JavaMailSender 빈 설정
- JavaMailSenderImpl 클래스는 Java Mail API를 이용, SMTP 프로토콜 사용
- SMTP 서버 주소와 포트 번호 필요
- host 프로퍼티 : 서버 주소
- port 프로퍼티 : 포트 번호, 기본 값 25
- defalutEncoding 프로퍼티 : 기본 인코딩 설정
- username 프로퍼티 : 인증을 위한 사용자명
- password 프로퍼티 : 인증을 위한 사용자 비밀번호
application.properties 에서 만들어주었음.
MailSender는 SimpleMailMessage를 정의해 텍스트 메일을 발송 할 수있는 반면,
JavaMailSender에선 MimeMessage를 정의해 본문이 HTML로 이루어진 메일을 발송할 수 있다.
user_email_verification_codes 테이블 만들기
email_verified_flag
:이메일 인증이 완료되었는가에 대한 여부
기재한 이메일로 실제 이메일을 전송할 것이고,
거기에 전송된 이메일을 클릭해야 회원가입이 될 것
created_at
:이 키가 언제 만들어졌는가?
expires_at
:해당 키를 언제까지 나타낼 것인가
expired_flag
:기본적으로 false. true가 되면 해당 키를 더 이상 사용할 수 없음.
salt
:보안성을 확보하기 위함
UserMapper.xml 에서
keyColumn
:users 테이블에 있는 인덱스 이름
keyProperty
:UserEntity에 있는 인덱스 이름
useGeneratedKeys
:자동생성 키 값들을 사용하기 위해서 사용된다는 것을 허용한다
(insert랑 update에만 적용)
UserService에서
System.out.println(userRegisterVo.getIndex());
적은 후
회원가입을 해보면 생성된 계정에 해당하는 인덱스번호가 뜬다.
pom.xml 에서 의존성 추가
UserService 에서
code를 난수화한다. Math.random 까지 해줌.
Entities에 UserEmailVerificationCodeEntity 생성
package dev.dmchoi.bbsbasic.entities;
import java.util.Date;
public class UserEmailVerificationCodeEntity {
private int index;
private Date createdAt; // 이 키가 언제 만들어졌는가
private Date expiresAt; // 해당 키를 언제까지 나타낼 것인가
private boolean isExpired; // 기본적으로 false. true가 되면 해당 키를 더 이상 사용할 수 없음.
private String code;
private String salt; // 보안성을 확보하기 위함
private int userIndex;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getExpiresAt() {
return expiresAt;
}
public void setExpiresAt(Date expiresAt) {
this.expiresAt = expiresAt;
}
public boolean isExpired() {
return isExpired;
}
public void setExpired(boolean expired) {
isExpired = expired;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public int getUserIndex() {
return userIndex;
}
public void setUserIndex(int userIndex) {
this.userIndex = userIndex;
}
}
그리고 UserService 에서 UserEmailVerificationCodeEntity 를 객체화.
IUserMapper 에서 추가
int insertUserEmailVerificationCode(UserEmailVerificationCodeEntity userEmailVerificationCodeEntity);
UserMapper.xml insertUserEmailVerificationCode 메소드 추가
회원가입 진행해보면 null 뜨고
두 테이블에 모두 레코드가 추가된다.
UserService에 내용 추가
:메일을 보내기 위해 사용할 객체
Java Mail API - MimeMessage 이용 메시지 생성
- 파일 첨부 또는 HTML로 구성되어 있는 경우 MimeMessage를 이용
- JavaMailSender 인터페이스는 MimeMessage 객체를 생성해주는 createMimeMessage() 메서드를 제공
- 이 메서드가 리턴한 MimeMessage 객체를 이용해서 메시지를 구성한 뒤 메일 발송
*MimeMessage 대신 SimpleMailMessage를 사용할 수도 있습니다. 둘의 차이점은 MimeMessage의 경우 멀티파트 데이터를 처리 할 수 있고 SimpleMailMessage는 단순한 텍스트 데이터만 전송이 가능합니다.
* 단순한 텍스트 메세지만 사용시엔 아래의 코드도 사용 가능
* MimeMessageHelper mailHelper = new MimeMessageHelper(mail,"UTF-8");
true로 하면 멀티파트 메세지를 사용하겠다는 의미
스프링에서 제공하는 헬퍼 객체이며, HTML 레이아웃, 이미지 삽입, 첨부파일 등 MIME 메시지를 생성할 수 있습니다.
- 생성자
MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, @Nullable String encoding)
또한 앞서 살펴본 SimpleMailMessage의 메서드를 모두 지원하고 있으며, 추가된 메서드는 다음과 같습니다.- messageHelper.setText - 메일 내용
두 번째 파라미터에 HTML 사용여부를 전달합니다.- messageHelper.addAttachment - 첨부 파일
첫 번째 파라미터에 메일에 노출된 파일 이름을 작성합니다.
두 번째 파라미터에 파일의 경로를 작성합니다.- messageHelper.addInline(contentId, fsr) - 이미지 삽입
첫 번째 파라미터에 삽입될 이미지의 id 애트리뷰트명을 작성합니다.
두 번째 파라미터에 파일의 경로를 작성합니다.- impleMailMessage
:이메일 메시지 정보를 작성합니다.- mimeMessageHelper.setTo(<받는사람 이메일="" 주소="">);
- mimeMessageHelper.setSubject(<이메일 제목="">);
타임리프를 사용중이라면 타임리프에서 제공하는 TemplateEngine 클래스의 process()메소드를 이용하면 된다.
이때, 타임리프에서 사용하는 파라미터값을 제공하기위해 스프링의 Model과 비슷한 역할을 하는 Context 객체에 뷰페이지에서 사용하는 파라미터를 정의하여, 타임리프로만든 HTML파일과 Context객체를 인자로 주게 되면, 알아서 HTML로 변환해주며, 이 변환된 문자열을 MimeMessage의 setText() 메소드 인자로 할당하면 HTML메일이 보내진다.
public void sendMail(){ Context context = new Context(); context.setVariable("nickname", "동민"); context.setVariable("message", "회원 가입을 진행하시려면 아래 링크를 클릭해 이메일 인증을 시도해주세요."); context.setVariable("host", "http://localhost:8080/"); // 메시지소스로 설정해두고 받아쓰면 참 편하다. context.setVariable("link", "email-authentication"); // 인증을 진행할 링크 context.setVariable("linkName", "여기를 클릭해주세요"); // 위 링크를 덧씌울 텍스트
MimeMessage에는 Multipart기능도 제공하기 때문에, 메일에 특정 첨부파일을 같이 보낼수도 있다.
templates파일에 emailVerificationTemplate.html 만들기
UserService 에서 SUCCESS 추가
회원가입 해보면 오류가 뜬다.
원인
검색을 해보니 사용중인 Google 계정에 대해서 "보안 수준이 낮은 앱 액세스"가 허용되지 않아서 메일을 보내는데 실패를 한 것으로 판단되었다.
2 단계 인증을 사용하는 계정에서는 사용할 수 없다고 함
재시도
성공
현재 html 코드까지 전부 뜬다. UserService 에서 setText에 true 추가
html이 구문으로 작동하기를 받아들일 것이냐? 에 대한 질문에 True를 주는 것.
인증하기 버튼도 뜬다!
register.html 에서
올바르게 회원가입 해보면
http://localhost:8080/ 로 이동한다.
즉 메인페이지.
UserController에서
입력받지 않은 모든 값들에 대해 기본값을 설정하자
enums에 UserLoginResult 생성
vos에 UserLoginVo 생성
UserController 에 있는 postLogin 메서드에
userLoginVo.setResult(null);
추가
UserService 에 login 메서드 생성
IUserMapper
UserEntity select(UserEntity userEntity);
추가
UserMapper.xml에 select
UserService
UserController 에 있는 postLogin 메서드에
this.userService.login(userLoginVo);
추가
그리고 ModelAndView 추가
templates 디렉토리에 login.html 생성
UserController 에 있는 postLogin 메서드에
modelAndView.setViewName("login");
추가
login.html에서 js로 prev 가져옴
UserController 에 있는 postLogin 메서드에
@RequestParam 지우고 Session 추가
참고 링크
JavaMailSender