๋ฉ์ผ๋ก ์์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ฐ๊ธํ๋ ค๋ฉด ์ผ๋จ SMTP๋ฅผ ์ฌ์ฉํด์ผํฉ๋๋ค.
์ ๋ ๊ตฌ๊ธ๋ก ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฉํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Gmail SMTP
Gmail SMTP๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์๋ 3๊ฐ์ง๋ฅผ ์ถฉ์กฑํด์ผ ํฉ๋๋ค.
- ๊ตฌ๊ธ ๊ณ์ ์ด 2๋จ๊ณ ์ธ์ฆ(OTP) ํ์ฑํ๋์ด ์์ ๊ฒ
- ์ฑ ๋น๋ฐ๋ฒํธ(App Password)๋ฅผ ๋ฐ๊ธ๋ฐ์ ๊ฒ
- Spring Boot ๋ฉ์ผ ์ค์ (application.properties)์ด SMTP ๊ท์น์ ๋ง์ ๊ฒ
ํ์ํ ์ฌ์ ์กฐ๊ฑด
1) ๊ตฌ๊ธ ๊ณ์ ์์ 2๋จ๊ณ ์ธ์ฆ ํ์ฑํ
๋งํฌ: https://support.google.com/accounts/answer/185839?hl=ko&co=GENIE.Platform%3DAndroid
→ “2๋จ๊ณ ์ธ์ฆ” ์ผ๊ธฐ
2๋จ๊ณ ์ธ์ฆ ์ฌ์ฉ - Android - Google ๊ณ์ ๊ณ ๊ฐ์ผํฐ
2๋จ๊ณ ์ธ์ฆ์ ์ฌ์ฉํ๋ฉด ๋น๋ฐ๋ฒํธ๊ฐ ๋์ฉ๋๋ ๊ฒฝ์ฐ์ ๋๋นํ์ฌ ๊ณ์ ๋ณด์์ ํ์ธต ๊ฐํํ ์ ์์ต๋๋ค. 2๋จ๊ณ ์ธ์ฆ์ ์ค์ ํ ํ์๋ ๋ค์์ ์ฌ์ฉํ์ฌ ๊ณ์ ์ ๋ก๊ทธ์ธํ ์ ์์ต๋๋ค. ๋น๋ฐ๋ฒํธ ๋ฐ 2
support.google.com
2) App Password ๋ฐ๊ธ
2๋จ๊ณ ์ธ์ฆ์ ์ผ ๋ค์ ์๋ ๋ฉ๋ด๊ฐ ๋ณด์ธ๋ค.

- ์ฑ: Mail
- ๊ธฐ๊ธฐ: ์ํ๋ ์ด๋ฆ(์: SpringBootServer)
→ 16์๋ฆฌ ๋น๋ฐ๋ฒํธ๊ฐ ์์ฑ๋จ
→ ์ด ์ฝ๋๊ฐ SMTP ๋น๋ฐ๋ฒํธ ์ญํ ์ ํ๋ค.
์ ์ฒด ๊ตฌ์ฑ
(1) application.properties ์ค์
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your_email@gmail.com
spring.mail.password=๋ฐ๊ธ๋ฐ์_์ฑ_๋น๋ฐ๋ฒํธ
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
(2) ์์กด์ฑ ์ถ๊ฐ (build.gradle)
implementation 'org.springframework.boot:spring-boot-starter-mail'
(3) ํ ํ๋ฆฟ ๋ฉ์ผ ๋ฐ์ก ์์ ์ฝ๋
- JavaMailSender + MimeMessageHelper๋ฅผ ์ด์ฉํด HTML ํ์์ผ๋ก ์ ๋ฌํด์ผ ํ๋ค.
- ๋ณ์๋ฅผ ํ ํ๋ฆฟ์ ๋ฐ์ธ๋ฉํ๋ ๋ก์ง์ด ์์ด์ผ ํ๋ค.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body style="font-family: Arial;">
<h2 th:text="${title}">๋ฉ์ผ ์ ๋ชฉ</h2>
<p th:text="${message}">๊ธฐ๋ณธ ๋ฉ์์ง</p>
<div style="margin-top:20px; padding:10px; border:1px solid #ddd;">
<p>๋ณด๋ธ ์๊ฐ: <span th:text="${sendTime}"></span></p>
</div>
</body>
</html>
public class MailDTO {
private String to;
private String subject;
private String title;
private String message;
}
@Service
@RequiredArgsConstructor
public class MailService {
private final JavaMailSender mailSender;
private final SpringTemplateEngine templateEngine;
public void sendTemplateMail(MailDTO dto) throws MessagingException {
// MIME ๋ฉ์ผ ๊ฐ์ฒด ์์ฑ
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// ์ ๋ชฉ / ๋ฐ๋์ฌ๋ ์ค์
helper.setTo(dto.getTo());
helper.setSubject(dto.getSubject());
// ํ
ํ๋ฆฟ์ ๋ฃ์ ๋ฐ์ดํฐ ๊ตฌ์ฑ
Context context = new Context();
context.setVariable("title", dto.getTitle());
context.setVariable("message", dto.getMessage());
context.setVariable("sendTime", LocalDateTime.now().toString());
// HTML ํ
ํ๋ฆฟ ๋ ๋๋ง
String html = templateEngine.process("mail/sample-mail", context);
// HTML ๋ฉ์ผ๋ก ์ค์
helper.setText(html, true);
mailSender.send(mimeMessage);
}
}
- templateEngine.process("mail/sample-mail", context);
→ templates/mail/sample-mail.html ํ์ผ์ ์ฝ์ด์ HTML์ ๋ง๋ค์ด์ค - helper.setText(html, true)
→ true = HTML์ด๋ผ๋ ์๋ฏธ - ๋ฉ์ผ ๋ด์ฉ์ variables(title, message, sendTime)์ ๋ชจ๋ ๋ฐ์ธ๋ฉํ ์ ์์.
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/mail")
public class MailController {
private final MailService mailService;
@PostMapping("/send-template")
public String sendTemplate(@RequestBody MailDTO dto) throws MessagingException {
mailService.sendTemplateMail(dto);
return "success";
}
}
์ ์ก ํ ์คํธ (POST)
POST /api/mail/send-template
{
"to": "๋ฐ์์ฌ๋@gmail.com",
"subject": "ํ
ํ๋ฆฟ ๋ฉ์ผ ํ
์คํธ",
"title": "ํ์ํฉ๋๋ค!",
"message": "ํ
ํ๋ฆฟ ๊ธฐ๋ฐ HTML ๋ฉ์ผ์ด ์ ์์ ์ผ๋ก ๋ฐ์ก๋์์ต๋๋ค."
}
์ด๋ฒ ๊ธ์ ๊ธฐ๋ณธ ์ค์ ๊ณผ ํ ํ๋ฆฟ ๊ธฐ๋ฐ ๋ฉ์ผ ๋ฐ์ก๊น์ง ์ ๋ฆฌํ ๋ด์ฉ์ด๋ค.
๋ ํ์ฅํ์ฌ ๋ค์ํ ๊ณณ์์๋ ํ์ฉํ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.