让我们从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的操作看起来没有太大的区别,所以转换也应该不困难。