ํ˜„์žฌ ์กฐ์ง์—์„œ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ ์—”์ง„์ธ ํƒ€์ž„๋ฆฌํ”„๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ด๋ฉ”์ผ ๋ฐœ์†ก์—๋Š” ํ”„๋ฆฌ๋งˆ์ปค ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•ด์„œ ๋ณ€ํ™˜ํ•œ HTML ํ˜•์‹์˜ ์ด๋ฉ”์ผ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋ฆฌ๋งˆ์ปค ํ…œํ”Œ๋ฆฟ ์—”์ง„

์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์€ ํƒ€์ž„๋ฆฌํ”„์ด๊ธฐ๋Š” ํ•˜์ง€๋งŒ ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฌธ๋ฒ•๊ณผ ๋‹ค๋ฅธ ํ…œํ”Œ๋ฆฟ ์—”์ง„๊ณผ์˜ ๋ Œ๋”๋ง ์„ฑ๋Šฅ ๋ฌธ์ œ๋กœ ์ธํ•˜์—ฌ ์ด๋ฉ”์ผ ๋ฐœ์†ก์ฒ˜๋Ÿผ ๋Œ€๋Ÿ‰์œผ๋กœ ๋ Œ๋”๋งํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค๋ฉด FreeMarker ๋˜๋Š” Mustache ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

ํ”„๋ฆฌ๋งˆ์ปค ์Šคํƒ€ํ„ฐ

์Šคํ”„๋ง ๋ถ€ํŠธ ํ”„๋ฆฌ๋งˆ์ปค ์Šคํƒ€ํ„ฐ ์˜์กด์„ฑ์„ ํ†ตํ•ด ํ”„๋ฆฌ๋งˆ์ปค ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-freemarker'
    implementation 'org.springframework.boot:spring-boot-starter-mail'
}

SMTP ๋ฉ”์ผ ์„œ๋ฒ„

์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” SMTP ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ผ ์„œ๋ฒ„๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๋ฌด๋ฃŒ ๋ฉ”์ผ ์„œ๋ฒ„ ์†”๋ฃจ์…˜์ด ์žˆ์œผ๋‚˜ ์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ๊ธ€์ด๋‚˜ ๋„ค์ด๋ฒ„ ์ด๋ฉ”์ผ ๊ณ„์ •์˜ ๋ช‡๊ฐ€์ง€ ์„ค์ •์„ ํ†ตํ•ด์„œ SMTP ๋ฉ”์ผ ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Gmail SMTP

์ง€๋ฉ”์ผ ๊ณ„์ •์œผ๋กœ ๋ฐœ์‹  ๋ฉ”์ผ ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ธ์ฆ ์˜ต์…˜๊ณผ ํ•จ๊ป˜ SSL(465) ๋˜๋Š” TLS(587)์šฉ ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

spring.mail.protocol=smtp
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=username@gmail.com
spring.mail.password=password
spring.mail.properties.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.test-connection=true
์ง€๋ฉ”์ผ ๊ณ„์ • ์ธ์ฆ ์˜ค๋ฅ˜

๋ฉ”์ผ ์„œ๋ฒ„ ์—ฐ๊ฒฐ ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ธ์ฆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ๋ณด์•ˆ ์ˆ˜์ค€์ด ๋‚ฎ์€ ์•ฑ์˜ ์•ก์„ธ์Šค๋ฅผ ํ—ˆ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Caused by: java.lang.IllegalStateException: Mail server is not available
...
Caused by: javax.mail.AuthenticationFailedException: 535-5.7.8 Username and Password not accepted. Learn more at

๋ณด์•ˆ ์ •์ฑ… ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ 2022๋…„ 5์›” 30์ผ๋ถ€ํ„ฐ๋Š” ์ง€๋ฉ”์ผ ๊ณ„์ •์œผ๋กœ SMTP ์„œ๋ฒ„๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋ฐ” ์ด๋ฉ”์ผ ๋ฐœ์†ก

์ง€๋ฉ”์ผ ๊ณ„์ •์œผ๋กœ SMTP ์„œ๋ฒ„์— ์ธ์ฆ๊นŒ์ง€ ์™„๋ฃŒํ–ˆ๋‹ค๋ฉด ์‹ค์ œ๋กœ ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ…Œ์ŠคํŠธ ํ•ด๋ณด์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@SpringBootTest
class GmailSmtpTests {

    @Autowired
    private JavaMailSenderImpl javaMailSender;

    @Test
    void sendMail() {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, StandardCharsets.UTF_8.name());

        mimeMessageHelper.setFrom("Mambo <kdevkr.gmail.com>");
        mimeMessageHelper.setTo("kdevkr@gmail.com");
        mimeMessageHelper.setSubject("Java Mail Test");
        mimeMessageHelper.setText("<h5>Hello World</h5>", true);

        javaMailSender.send(mimeMessage);
    }
}

ํ”„๋ฆฌ๋งˆ์ปค ํ…œํ”Œ๋ฆฟ ์ ์šฉํ•˜๊ธฐ

ํ”„๋ฆฌ๋งˆ์ปค ํ…œํ”Œ๋ฆฟ ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๊ณ  ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•ด์„œ HTML ํ˜•์‹์˜ ๋ฌธ์ž์—ด์„ ์ด๋ฉ”์ผ ๋‚ด์šฉ์œผ๋กœ ์ „๋‹ฌํ•˜์—ฌ ๋ฐœ์†กํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ €๋Š” HTML Email Template ๋งŒ๋“ค๊ธฐ๋ผ๋Š” ๊ธ€์„ ์ฐธ๊ณ ํ•˜์—ฌ ํ…œํ”Œ๋ฆฟ์„ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

@SpringBootTest
class GmailSmtpTests {

    @Autowired
    private JavaMailSenderImpl javaMailSender;

    @Autowired
    private FreeMarkerConfigurationFactoryBean configurationFactoryBean;

    @Test
    void sendMail() {
        Configuration configuration = configurationFactoryBean.createConfiguration();
        Template template = configuration.getTemplate("email.ftlh");

        Map<String, Object> model = new HashMap<>();
        model.put("title", "Java Mail Test");
        model.put("content", "Hello World");
        String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);

        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, StandardCharsets.UTF_8.name());

        mimeMessageHelper.setFrom("Mambo <kdevkr.gmail.com>");
        mimeMessageHelper.setTo("kdevkr@gmail.com");
        mimeMessageHelper.setSubject("Java Mail Test with FreeMarker");
        mimeMessageHelper.setText(content, true);

        javaMailSender.send(mimeMessage);
    }
}

๊ธฐ๋ณธ ํ”„๋ฆฌ๋งˆ์ปค ํ…œํ”Œ๋ฆฟ ํด๋”๋Š” ํด๋ž˜์ŠคํŒจ์Šค์˜ templates ์ž…๋‹ˆ๋‹ค.
spring.freemarker.template-loader-path=classpath:/templates/

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ