๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๋ฐ˜์‘ํ˜•

๋ฉ”์ผ๋กœ ์ž„์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ฐœ๊ธ‰ํ•˜๋ ค๋ฉด ์ผ๋‹จ 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 ๋ฉ”์ผ์ด ์ •์ƒ์ ์œผ๋กœ ๋ฐœ์†ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
}

 

์ด๋ฒˆ ๊ธ€์€ ๊ธฐ๋ณธ ์„ค์ •๊ณผ ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜ ๋ฉ”์ผ ๋ฐœ์†ก๊นŒ์ง€ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ด๋‹ค.

๋” ํ™•์žฅํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๊ณณ์—์„œ๋„ ํ™œ์šฉํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

 

 

 

๋ฐ˜์‘ํ˜•