회원 비밀번호 찾기 기능을 만들 때, 임시 비밀번호를 생성하고 이메일로 발송하는 기능은 많은 서비스에서 필요한 로직입니다.
이번 글에서는 Spring Boot에서 Gmail SMTP를 이용해 이메일을 보내는 방법과 임시 비밀번호 생성/업데이트 흐름까지 모두 정리합니다.
이메일 전송을 위해서는 spring-boot-starter-mail 의존성이 필요합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
이 의존성을 통해 JavaMailSender, MimeMessage, MimeMessageHelper 등을 사용할 수 있게 됩니다.
application.properties)# Gmail SMTP 기본 설정
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=YOUR_GMAIL_ADDRESS
spring.mail.password=YOUR_APP_PASSWORD
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
spring.mail.properties.mail.transport.protocol=smtp
| 옵션 | 역할 |
|---|---|
spring.mail.host | Gmail SMTP 서버 주소 |
spring.mail.port | SMTP 포트 (TLS: 587) |
spring.mail.username | Gmail 계정 이메일 |
spring.mail.password | 앱 비밀번호 |
mail.smtp.auth | SMTP 로그인 인증 사용 |
mail.smtp.starttls.enable | TLS 보안 연결 활성화 |
mail.smtp.starttls.required | TLS 필수 적용 |
mail.smtp.ssl.trust | Gmail 인증서 신뢰 |
mail.transport.protocol | SMTP 프로토콜 사용 |
⚠️ Gmail은 실제 비밀번호를 넣으면 안 되고
Google 앱 비밀번호(App Password)를 발급받아 사용해야 합니다.
앱 비밀번호 발급방법은 제 블로그에 추가적으로 작성해뒀습니다 !
임시 비밀번호를 생성하고, 해당 비밀번호를 사용자 DB에 업데이트한 뒤, 이메일로 발송하는 핵심 로직입니다.
sendPasswordByEmail() — 메일 발송 메서드private boolean sendPasswordByEmail(String toEmail, String userId, String userName) {
try {
// 6자리 임시 비밀번호 생성
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 6; i++) {
sb.append(chars.charAt(random.nextInt(chars.length())));
}
String tempPassword = sb.toString();
// DB 비밀번호 업데이트
Map<String, Object> updateParam = new HashMap<>();
updateParam.put("m_user_id", userId);
updateParam.put("m_user_pw", tempPassword);
testMapper.updateUserPassword(updateParam);
// 메일 생성
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom("발신자 이메일 주소");
helper.setTo(toEmail);
helper.setSubject("임시 비밀번호 안내");
String htmlContent =
"<html><body>" +
"<h3>임시 비밀번호 안내</h3>" +
"<p>안녕하세요, " + userName + "님.</p>" +
"<p>요청하신 임시 비밀번호는 다음과 같습니다.</p>" +
"<h2>" + tempPassword + "</h2>" +
"<p>로그인 후 반드시 비밀번호를 변경해주세요.</p>" +
"</body></html>";
helper.setText(htmlContent, true);
mailSender.send(message);
return true;
} catch (Exception e) {
return false;
}
}
DB 조회 후 사용자 이메일이 확인되면 sendPasswordByEmail()을 호출합니다.
@Override
public ApiResult findUserPw(Map<String, Object> param) {
ApiResult apiResult = ApiResult.builder()
.status(ApiResult.STATUS_SUCCESS)
.build();
try {
// 입력값 검증
if (param.get("m_user_id") == null
|| param.get("m_user_id").toString().trim().isEmpty()) {
return apiResult;
}
if (param.get("m_user_email") == null
|| param.get("m_user_email").toString().trim().isEmpty()) {
return apiResult;
}
// DB 조회
List<Map<String, Object>> resultList = testMapper.findUserPwCheck(param);
if (resultList != null && !resultList.isEmpty()) {
Map<String, Object> row = resultList.get(0);
String userId = (String) row.get("user_id");
String userEmail = (String) row.get("user_email");
String userNm = (String) row.get("user_nm");
// 이메일 전송
if (userEmail != null) {
boolean emailSent = sendPasswordByEmail(userEmail, userId, userNm);
if (!emailSent) {
return apiResult;
}
}
apiResult.setData("rsData", resultList);
}
} catch (Exception ex) {
apiResult.setStatusMsg(ApiResult.STATUS_ERROR, "시스템 오류가 발생했습니다.");
}
return apiResult;
}
| 클래스 | 역할 |
|---|---|
MimeMessage | 이메일 메시지 객체(본문, 첨부파일, HTML 지원) |
MimeMessageHelper | MimeMessage를 쉽게 조작하기 위한 도우미 클래스 |
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
true → HTML/첨부파일(멀티파트) 허용"UTF-8" → 문자열 인코딩 설정이번 글에서 정리한 내용:
비밀번호 찾기는 단순한 기능 같지만
보안, 성능, UI까지 신경 써야 할 요소들이 많기 때문에
정석대로 구현해두면 이후 기능 확장에도 도움이 됩니다.