使用 Spring Boot 傳送 Email

Photo by Elena Mozhvilo on Unsplash
Photo by Elena Mozhvilo on Unsplash
後端程式常常需要寄信給使用者,如註冊完成、忘記密碼、訂購完成等等。本文章將介紹如何利用 FreeMarker 建立信件模板,並利用 Spring Mail 透過 Gmail SMTP 傳送 email。

後端程式常常需要寄信給使用者,如註冊完成、忘記密碼、訂購完成等等。本文章將介紹如何利用 FreeMarker 建立信件模板,並利用 Spring Mail 透過 Gmail SMTP 傳送 email。

完整程式碼可以在 下載。

Table of Contents
  1. FreeMarker
  2. Spring Mail
  3. 結語

FreeMarker

FreeMarker 是一個 template engine,可以用來建立 email 內容的模板。首先,我們要引入以下的依賴。

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-freemarker")
}

在 application.properties 中,加入以下的設定。spring.freemarker.template-loader-path 是用來設定模板檔案的位址。在以下的範例中,我們將它設定為在 src/resources/templates/ 下。

spring.freemarker.cache=true
spring.freemarker.template-loader-path=classpath:/templates/

在 src/resources/templates/ 下新增模板檔案 EmailTemplate.ftlh,其內容如下。在模板檔案的內容中,有兩個變數,${logo}${content}。之後,在程式中可以在變數的地方取代我們想要的資料。

<html>
<body>

<div>
    <img src="cid:${logo}" />
</div>
<br/>
<div>${content}</div>

</body>
</html>

Spring Mail

接下來,我們將利用 Spring Mail 來透過 STMP 傳送 email。首先,我們要引入以下的依賴。

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-mail")
}

在 application.properties 中,我們用 Gmail STMP 作為 SMTP server。

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=<login username to smtp server>
spring.mail.password=<login password to smtp server>
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.debug=true

現在所有的設定都完成了。接下來,我們將利用以下的程式碼來傳送 email。在程式碼中,我們是用 JavaMailSender 來傳送 email,可是我們並沒有引入 JavaMailSender 的依賴啊。這是因為 Spring Mail 是基於 JavaMailSender 來實現傳送 email 的功能。

首先,我們呼叫 JavaMailSender.createMimeMessage() 來建立一個 MimeMessage。然後,利用 MimeMessageHelper 來設定 email 的傳送者(from)、接收者(to)和主旨(subject)。

用 FreeMarker 載入模板檔案,並呼叫 FreeMarkerTemplateUtils.processTemplateIntoString() 將信件的 logo 和內容填入模板中。然呼叫 MimeMessageHelper.setText() 將模板內容傳入 MimeMessage。然後,呼叫 MimeMessageHelper.addInline() 將 logo 檔案加入到 MimeMessage 中。值得注意的是,addInline() 必須要在 setText() 之後呼叫,不然 logo 不會顯示出來。

最後,呼叫 JavaMailSender.send() 送出 email。

@Service
class EmailService(private val javaMailSender: JavaMailSender, private val freemarkerConfig: Configuration) {
    fun sendEmail(to: String, subject: String, content: String) {
        val mimeMessage = javaMailSender.createMimeMessage()
        val helper = MimeMessageHelper(mimeMessage, true)
        helper.setFrom("Wayne's Talk <waynestalk@gmail.com>")
        helper.setTo(to)
        helper.setSubject(subject)

        val logoClassPathResource = ClassPathResource("static/logo.png")
        val logo = ByteArrayResource(logoClassPathResource.inputStream.readAllBytes())

        val parameters = mapOf(
            "logo" to "logo.png",
            "content" to content,
        )

        val template = freemarkerConfig.getTemplate("EmailTemplate.ftlh")
        val text = FreeMarkerTemplateUtils.processTemplateIntoString(template, parameters)
        helper.setText(text, true)

        // This line must be after helper.setText(), otherwise the logo won't be displayed
        helper.addInline("logo.png", logo, "image/png")

        javaMailSender.send(mimeMessage)
    }
}

結語

Spring Mail 使用起來相當地簡單。主要的問題是如何產生出複雜的信件內容。而這部分可以用 FreeMarker 輕鬆地達成。這兩個套件搭配起來使用,可以輕易地產生出複雜的信件。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

You May Also Like
Photo by Charles Jackson on Unsplash
Read More

Springdoc-OpenAPI 教學

Springdoc 是一個整合 OpenAPI Specification 和 Spring Boot 的套件。和 SpringFox 套件一樣,它產出 Swagger 文件。兩者不同在於,Springdoc 是用 Swagger 3,而 SpringFox 是用 Swagger 2。
Read More