让我们从Spring Boot2发送电子邮件

首先

我认为当谈到使用Java(Kotlin)发送电子邮件时,大多数人会选择使用javamail,但由于spring也具有电子邮件功能,所以我研究了这方面的功能。

在代码包中有一个名为databasetest的源代码文件,但只是重复使用了另一个人的代码,请不要在意。

环境

Kotlin 是一种编程语言,Spring-boot 2.0.1.RELEASE 是一个框架版本。

我使用smtp4dev作为SMTP服务器。虽然FakeSMTP更简单,但作为正式使用时有些部分不够完整,所以我放弃了。虽然喜欢它的简单性。

依赖

这次我们使用Maven进行操作,需要在pom.xml中添加以下内容。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

先试着发送一封简单的电子邮件。

我暂时发送一封简单的文本邮件试试看。

spring.mail.host=localhost
spring.mail.port=25
package com.tasogarei.databasetest.contorller

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.mail.MailException
import org.springframework.mail.MailSender
import org.springframework.mail.SimpleMailMessage
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody

@Controller
class MailController {
    @Autowired
    lateinit var mailSender : MailSender

    @ResponseBody
    @GetMapping("/mail")
    fun sendmail() : ResponseEntity<String> {
        var message = SimpleMailMessage().apply {
            setFrom( "test@test.jp")
            setTo("tasogarei34@gmail.com")
            setSubject("test subject")
            setText("test body")
        }
        try {
            mailSender.send(message)
        } catch (e : MailException) {
            // do not something
        }
        return ResponseEntity.ok().build()
    }
}

只需要这么做就没有问题。
由于支持SmtpAuth,您只需添加一些属性即可实现这些。
即使要将MTA更改为Gmail并发送,也很容易实现。
但请注意,如果不进行这边的设置,应用程序将无法发送。
由于很容易将邮件发送到外部,所以我认为最好不要使用此设置来确认发送电子邮件。
嗯,虽然自己的MTA设置很麻烦,但smtp4dev也支持SmtpAuth,所以我们使用它来进行测试吧。

我只会列举基本设置。

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username={your mail address}
spring.mail.password={your password}
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

将模板注册到Bean并发送。

由於SimpleMailMessage可以被註冊為一個Bean,所以可以將其註冊為模板,並在其他地方設定可變部分後進行發送。
因為這種方式不太直觀,我覺得最好不要使用。

spring.mail.host=localhost
spring.mail.port=25
package com.tasogarei.databasetest.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.mail.SimpleMailMessage
import org.springframework.stereotype.Component

@Component
@Configuration
class MailConfig {

    @Bean("templateMessage")
    fun template() : SimpleMailMessage {
        var template = SimpleMailMessage()
        template.setFrom("tasogarei34@gmail.com")
        template.setTo("test@test.jp")
        template.setSubject("test subject")
        template.setText("test body")
        return template
    }
}
package com.tasogarei.databasetest.contorller

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.mail.MailException
import org.springframework.mail.MailSender
import org.springframework.mail.SimpleMailMessage
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody

@Controller
class MailController {
    @Autowired
    lateinit var mailSender : MailSender

    @Autowired
    lateinit var templateMessage : SimpleMailMessage

    @ResponseBody
    @GetMapping("/mail")
    fun sendmail() : ResponseEntity<String> {
        try {
            mailSender.send(templateMessage)
        } catch (e : MailException) {
            println(e.message)
        }
        return ResponseEntity.ok().build()
    }
}

只需注册多个Bean模板,就可以创建相应数量的模板注册。

package com.tasogarei.databasetest.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.mail.SimpleMailMessage
import org.springframework.stereotype.Component

@Component
@Configuration
class MailConfig {

    @Bean("templateMessage")
    fun template() : SimpleMailMessage {
        var template = SimpleMailMessage()
        template.setFrom("tasogarei34@gmail.com")
        template.setTo("test@test.jp")
        template.setSubject("test subject")
        template.setText("test body")
        return template
    }

    @Bean("template2Message")
    fun template2() : SimpleMailMessage {
        var template = SimpleMailMessage()
        template.setFrom("tasogarei34@gmail.com")
        template.setTo("test@test.jp")
        template.setSubject("test subject2")
        template.setText("test body2")
        return template
    }
}
package com.tasogarei.databasetest.contorller

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.mail.MailException
import org.springframework.mail.MailSender
import org.springframework.mail.SimpleMailMessage
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody

@Controller
class MailController {
    @Autowired
    lateinit var mailSender : MailSender

    @Autowired
    lateinit var templateMessage : SimpleMailMessage

    @Autowired
    lateinit var template2Message : SimpleMailMessage

    @ResponseBody
    @GetMapping("/mail")
    fun sendmail() : ResponseEntity<String> {
        try {
            mailSender.send(templateMessage)
        } catch (e : MailException) {
            println(e.message)
        }
        return ResponseEntity.ok().build()
    }

    @ResponseBody
    @GetMapping("/mail2")
    fun sendmail2() : ResponseEntity<String> {
        try {
            mailSender.send(template2Message)
        } catch (e : MailException) {
            println(e.message)
        }
        return ResponseEntity.ok().build()
    }
}

发送HTML邮件

因为现在这样的话无法发送丰富的内容,所以我想尝试发送HTML。
发送HTML非常简单,但与仅纯文本有一些不同。

作为更改的要点,
1. 使用JavaMailSender而不是MailSender来发送邮件。
2. 通过实现MimeMessagePreparator而不是SimpleMailMessage来创建消息。

MimeMessagePreparator是一种非常简单的Helper类,可以使用MimeMessageHelper轻松地设置值,因此使用它会很好。
尤其是Kotlin的实现,让人感到特别轻松和清爽,可以实现一个很好的感觉。

由于内容不变,我在这里省略在application.properties中写的内容。

package com.tasogarei.databasetest.contorller

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.mail.MailException
import org.springframework.mail.javamail.JavaMailSender
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody
import javax.mail.internet.InternetAddress
import org.springframework.mail.javamail.MimeMessageHelper

@Controller
class MailController {
    @Autowired
    lateinit var mailSender : JavaMailSender

    @ResponseBody
    @GetMapping("/mail")
    fun sendmail() : ResponseEntity<String> {
        try {
            mailSender.send({ mimeMessage ->
                MimeMessageHelper(mimeMessage, true, "UTF-8").apply {
                    setTo("tasogarei@gmail.com")
                    setFrom(InternetAddress("test@test.jp"))
                    setSubject("test subject")
                    setText("text part", "<html><body>html</body></html>")
                }
            })
        } catch (e : MailException) {
            println(e.message)
        }
        return ResponseEntity.ok().build()
    }
}

跨越各种繁琐之后,真的很轻松。
顺便提一下,如果要包含附件文件的话,可以在MimeMessageHelper的addAttachment()方法中指定,它会将其视为附件文件处理。
参数可以传递多种,这里暂且举例说明如何添加位于/src/main/resource目录下的文件作为附件。

addAttachment("test.txt",DefaultResourceLoader().getResource("classpath:test.txt").file )

“给予envelop from”

在业务层面上,有时会出现 envelope from 和 from 不同的情况,下面是实现此功能的方法。
我们可以使用一个方便设置的类 SMTPMessage 来实现。由于它可以从 MimeMessage 进行转换,我们可以使用 Helper 类创建 MimeMessage,并通过转换和设置来实现发送的流程。

顺便提一下,我看样子无法通过Helper来设置Header,所以如果想要自定义Header的话,似乎需要将其转换为MimeMessage并进行设置。
为什么不让我这样做,我完全不明白。。。

由于需要对Message-ID进行updateMessageID()的覆盖,所以如果要执行此操作,则仍需继承MimeMessage进行实现。

package com.tasogarei.databasetest.contorller

import com.sun.mail.smtp.SMTPMessage
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.mail.MailException
import org.springframework.mail.javamail.JavaMailSender
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody
import javax.mail.internet.InternetAddress
import org.springframework.mail.javamail.MimeMessageHelper

@Controller
class MailController {
    @Autowired
    lateinit var mailSender : JavaMailSender

    @ResponseBody
    @GetMapping("/mail")
    fun sendmail() : ResponseEntity<String> {
        var messageHelper = MimeMessageHelper(mailSender.createMimeMessage(), true, "UTF-8").apply {
            setTo("tasogarei@gmail.com")
            setFrom(InternetAddress("test@test.jp"))
            setSubject("test subject")
            setText("text part", "<html><body>html</body></html>")
        }
        var message = SMTPMessage(messageHelper.mimeMessage).apply {
            envelopeFrom = "envelop@test.jp"
        }
        try {
            mailSender.send(message)
        } catch (e : MailException) {
            println(e.message)
        }
        return ResponseEntity.ok().build()
    }
}

最后

尽管JavaMail仍在进行开发,但目前没有积极进行更改的理由。然而,如果您正在使用Spring,那么使用SpringMail可以轻松表示MultiPart的选择是非常合适的选择。从表面上看,JavaMail和SpringMail的操作看起来没有太大的区别,所以转换也应该不困难。

广告
将在 10 秒后关闭
bannerAds