
SMTP (Simple Mail Transfer Protocol): 이메일을 전송하는 데 사용되는 표준 통신 프로토콜.
* -> 이메일 클라이언트가 이메일을 작성하여 전송할 때, SMTP 서버를 통해 수신자의 이메일
* 서버로 메일을 전달하는 역할
* -> 기본적으로 포트 25를 사용하지만, 보안을 강화한 포트 587이나 포트
* 465(SSL/TLS)가 자주 사용됨
*
* 동작방식
*
1. Spring Boot 애플리케이션에서 내가 이메일을 보냄
2. Google SMTP 서버로 전송 (Google 서버가 "중간 배달자" 역할을 하는 셈)
3. Google SMTP 서버가 이메일 주소에 맞는 최종 수신자의 이메일 서버(예: Gmail, Yahoo,
회사 이메일 서버)로 이메일을 다시 보냄.
4. 수신자가 이메일을 받음
*
*
* (참고)
* HTTP (Hypertext Transfer Protocol): 웹 브라우저와 서버 간에 웹 페이지나 파일을
* 주고받는 데 사용
*
* 전송 방향
* - HTTP: 클라이언트-서버 간 통신을 기반으로 하며, 클라이언트가 서버에 요청(Request)을
* 보내고 서버가 응답(Response).
* - SMTP: 서버 간 통신이 가능하며, 이메일을 발신 서버에서 수신 서버로 전달하는 식으로
* 동작함.
개발자 쪽에서 EMAIL이 전달 ⇒ Google SMTP가 받음 ⇒ 사용자
⇒ 즉, Google SMTP는 중간 배달자 역할을 함
⇒ 구글에서 만든 SMTP 프로토콜을 사용하는 것, 사용자는 어떠한 이메일 형식이든 상관이 없음
⇒ properties에 작성된 내용 중 key가 일치하는 value값을 얻어와 필드에 대입
public class EmailConfig {
.
.
@Value("${spring.mail.username}")
private String userName;
@Value("${spring.mail.password}")
private String password;
.
.
// ${} 안에 key값 넣기
}



spring.mail.username=이메일
spring.mail.password=생성된 앱 비밀번호 (빈칸없이)
package edu.kh.project.common.config;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Configuration
@PropertySource("classpath:/config.properties")
// classpath => src/main/resources
// properties에 있는 코드를 가져오기 위해 쓰는 어노테이션
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmailConfig {
/*
*
* SMTP (Simple Mail Transfer Protocol): 이메일을 전송하는 데 사용되는 표준 통신 프로토콜. -> 이메일
* 클라이언트가 이메일을 작성하여 전송할 때, SMTP 서버를 통해 수신자의 이메일 서버로 메일을 전달하는 역할 -> 기본적으로 포트 25를
* 사용하지만, 보안을 강화한 포트 587이나 포트 465(SSL/TLS)가 자주 사용됨
*
* 동작방식
*
* 1. Spring Boot 애플리케이션에서 내가 이메일을 보냄 2. Google SMTP 서버로 전송 (Google 서버가 "중간 배달자"
* 역할을 하는 셈) 3. Google SMTP 서버가 이메일 주소에 맞는 최종 수신자의 이메일 서버(예: Gmail, Yahoo, 회사
* 이메일 서버)로 이메일을 다시 보냄. 4. 수신자가 이메일을 받음
*
*
* (참고) HTTP (Hypertext Transfer Protocol): 웹 브라우저와 서버 간에 웹 페이지나 파일을 주고받는 데 사용
*
* 전송 방향 - HTTP: 클라이언트-서버 간 통신을 기반으로 하며, 클라이언트가 서버에 요청(Request)을 보내고 서버가
* 응답(Response). - SMTP: 서버 간 통신이 가능하며, 이메일을 발신 서버에서 수신 서버로 전달하는 식으로 동작함.
*/
// @Value : properties에 작성된 내용 중
// key가 일치하는 value값을 얻어와 필드에 대입
@Value("${spring.mail.username}")
private String userName;
@Value("${spring.mail.password}")
private String password;
@Bean
public JavaMailSender javaMailSender() {
// Spring 에서 JavaMailSender를 구성하는 Bean을 정의하고자 만든 메서드
// JavaMailSender : 이메일을 보내는데 사용되는 인터페이스로
// JavaMailSenderImpl 클래스를 통해 직접적으로 구현됨.
// SMTP 서버를 사용하여 이메일을 보내기 위한 구성을 제공함
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
Properties prop = new Properties();
prop.setProperty("mail.transport.protocol", "smtp"); // 전송 프로토콜을 설정. 여기서는 SMTP를 사용
prop.setProperty("mail.smtp.auth", "true"); // SMTP 서버 인증을 사용할지 여부를 설정함.
// true로 설정되어 있으므로 인증이 사용됨
// SMTP 서버를 사용하여 이메일을 보내려면 보안 상의 이유로 인증이 필요.
// (사용자이름(이메일)과 비밀번호(앱비밀번호) 확인)
prop.setProperty("mail.smtp.starttls.enable", "true"); // STARTTLS를 사용하여 안전한 연결을 활성화할지 여부를 설정
prop.setProperty("mail.debug", "true"); // 디버그 모드를 설정
prop.setProperty("mail.smtp.ssl.trust", "smtp.gmail.com"); // 신뢰할 수 있는 SMTP 서버 호스트를 지정
prop.setProperty("mail.smtp.ssl.protocols", "TLSv1.2"); // SSL 프로토콜을 설정. 여기서는 TLSv1.2를 사용
mailSender.setUsername(userName); // 이메일 계정의 사용자
mailSender.setPassword(password); // 이메일 계정의 비밀번호
mailSender.setHost("smtp.gmail.com"); // SMTP 서버 호스트를 설정.
mailSender.setPort(587); // SMTP 서버의 포트 587로 설정
mailSender.setDefaultEncoding("UTF-8"); // 기본 인코딩 설정
mailSender.setJavaMailProperties(prop);
// JavaMail의 속성을 설정(앞서 정의해 둔 prop에 있는 설정들을 적용한 것)
return mailSender;
// 위처럼 각종 설정이 적용된 JavaMailSender를
// Bean으로 등록하여
// Spring 애플리케이션에서 이메일을 보내기 위한 구성을 제공함
}
}
<div class="signUp-input-area">
<input
type="text"
name="memberEmail"
id="memberEmail"
placeholder="아이디(이메일)"
maxlength="30"
autocomplete="off"
/>
<button id="sendAuthKeyBtn" type="button">인증번호 받기</button>
</div>

인증번호 받기 클릭 시
sendAuthKeyBtn.addEventListener("click", () => {
.
.
.
fetch("/email/signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: memberEmail.value,
// 단일값인 경우 JSON 형식으로 전달이 됌
})
.then((resp) => resp.text())
.then((result) => {
if (result == 1) {
console.log("인증 번호 발송 성공");
} else {
console.log("인증 번호 발송 실패!!!");
}
});
.
.
});
@ResponseBody
@PostMapping("signup")
public int signup(@RequestBody String email) {
String authKey = service.sendEmail("signup", email);
if (authKey != null) {
// 인증번호가 반환되어 돌아옴
// == 이메일 보내기 성공
return 1;
}
// 이메일 보내기 실패
return 0;
}
⇒ signup 메서드를 통해서
인증키 생성(UUID)
인증키 update or insert
@Transactional(rollbackFor = Exception.class) // 메서드 레벨에서도 이용 가능
public boolean storeAuthKey(Map<String, String> map) {
// 1. 기존 이메일에 대한 인증키 update 수행
int result = mapper.updateAuthKey(map);
// 2. update 실패 시 insert 수행
if (result == 0) {
result = mapper.insertAuthKey(map);
}
// 3. 성공 여부 반환 (true / false)
return result > 0;
}
⇒ 생성 여부에 따라서
if (!storeAuthKey(map)) {
return null;
}
위와 같이 DB 저장이 실패를 했다면 null, 아니면 다음 단계로
MimeMessage mimeMessage = mailSender.createMimeMessage();
// 메일 발송 시 사용하는 객체
try {
// 메일 발송을 도와주는 Helper 클래스 사용해서 파일 첨부 or html 등 템플릿으로 설정해서 보낼지
// 쉽게 처리할 수 있도록 도와주는 클래스
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// - mimeMessage : MimeMessage 객체로, 이메일 메시지의 내용을 담고있음
// (이메일의 본문, 제목, 수신자 정보 등을 포함하고 있음)
// - true : 파일 첨부를 사용할 지 말지에 대한 여부를 지정해주는 것
// (파일첨부 및 내부 이미지 삽입 가능)
// - "UTF-8" : 이메일 내용이 UTF-8 인코딩으로 전송
// 메일 기본 정보 셋팅
helper.setTo(email); // 받는 사람(수신자)
helper.setSubject("[boardProject] 회원 가입 인증번호 입니다."); // 제목 세팅
helper.setText(loadHtml(authKey, type), true);
// setText => html을 보내고 싶을 때, 첫번째는 html결과, 그리고 true는 html 요소를
// 전달할지 말지에 대한 매개변수
// HTML 내용 설정
// helper.setText("인증번호 입니다 : " + authKey);
// 인증번호 입니다 : agdsey
// 메일에 이미지를 첨부할 것인데, 어떤 이미지를 첨부할 지 넣는것(여기선 로고를 넣을 것)
helper.addInline("logo", new ClassPathResource("static/images/logo.jpg"));
// 실제 메일 발송
mailSender.send(mimeMessage);
return authKey;
} catch (Exception e) {
e.printStackTrace();
return null; // 메일 발송 실패 시 null 반환
}

