前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Spring Mail和FreeMaker发送HTML邮件

使用Spring Mail和FreeMaker发送HTML邮件

作者头像
MashiroT
发布2023-10-18 15:39:41
1480
发布2023-10-18 15:39:41
举报
文章被收录于专栏:MashiroのBlog

使用Spring Mail和FreeMaker发送HTML邮件

引言

最近在写自己的博客项目,有收到新评论后发送邮件通知的功能,使用MQ通知服务,使用了没接触过的FreeMaker和JavaMail,记录一下实现过程,代码仓库:https://github.com/mashirot/MashiroBlog/tree/master/mail-service

实现

项目结构:

代码语言:javascript
复制
└─src
   └─main
      ├─kotlin
      │  └─ski
      │      └─mashiro
      │          │  MailServiceApplication.kt
      │          │
      │          ├─annotation
      │          │      Slf4j.kt
      │          │
      │          ├─config
      │          │      JacksonConfig.kt
      │          │
      │          ├─constant
      │          │      RabbitMQConsts.kt
      │          │
      │          ├─dto
      │          │      CommentMailDTO.kt
      │          │
      │          ├─listener
      │          │      MailQueueListener.kt
      │          │
      │          └─service
      │              │  MailService.kt
      │              │
      │              └─impl
      │                      MailServiceImpl.kt
      │
      └─resources
          │  application.yml
          │
          └─templates
                  CommentAdvice.ftlh

环境

Springboot 3.1.2JDK17Kotlin 1.8.22

依赖

代码语言:javascript
复制
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-amqp")
    implementation("org.springframework.boot:spring-boot-starter-mail")
    implementation("org.springframework.boot:spring-boot-starter-freemarker")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.springframework.amqp:spring-rabbit-test")
    implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2")
    implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2")
}

代码

Jackson配置
代码语言:javascript
复制
/**
 * @author MashiroT
 */
@Configuration
class JacksonConfig {
    @Bean
    fun objectMapper(): ObjectMapper {
        return ObjectMapper().registerModule(JavaTimeModule())
    }
}
@Slf4j注解
代码语言:javascript
复制
/**
 * @author MashiroT
 */
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Slf4j {
    companion object {
        val <reified T> T.log: Logger
            inline get() = LoggerFactory.getLogger(T::class.java)
    }
}
MQ监听
代码语言:javascript
复制
/**
 * @author MashiroT
 */
@Component
class MailQueueListener(
    val mailService: MailService
) {
    @RabbitListener(queues = [RabbitMQConsts.MAIL_QUEUE])
    fun listenMailQueue(msg: String) {
        mailService.sendNewCommentAdvice2Owner(msg)
    }
}
MailService
代码语言:javascript
复制
/**
 * @author MashiroT
 */
@Service
@Slf4j
class MailServiceImpl(
    val objectMapper: ObjectMapper,
    val mailSender: JavaMailSender,
    val freeMakerConfiguration: Configuration,

) : MailService {
    @Value("\${blog.from}")
    private var from: String? = null

    @Value("\${blog.to}")
    private var to: String? = null

    override fun sendNewCommentAdvice2Owner(msg: String) {
        try {
            val commentMailDTO = objectMapper.readValue(msg, CommentMailDTO::class.java)

            // 使用MimeMessage发送复杂邮件,如无需求可使用MailSender配合SimpleMailMessage使用
            val mimeMessage = mailSender.createMimeMessage()
            val mimeMessageHelper = MimeMessageHelper(mimeMessage, "utf-8")
            // 发送人邮箱
            mimeMessageHelper.setFrom(from!!)
            // 收件人邮箱
            mimeMessageHelper.setTo(to!!)
            val title = "你的帖子「${commentMailDTO.articleTitle}」有新回复"
            // 邮件主题
            mimeMessageHelper.setSubject(title)

            val map = mapOf(
                "title" to title,
                "senderNickname" to commentMailDTO.senderNickname!!,
                "content" to if (commentMailDTO.content!!.length > 50) commentMailDTO.content.substring(
                    0,
                    50
                ) else commentMailDTO.content
            )
            // 获取Template模板,默认路径为classpath:/templates/
            val template = freeMakerConfiguration.getTemplate("CommentAdvice.ftlh")
            // 传入参数并转为string
            val text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map)

            // 邮件正文
            mimeMessageHelper.setText(text, true)
            // 发送日期(不填默认当前)
            mimeMessageHelper.setSentDate(Date())

            mailSender.send(mimeMessage)
            log.info("文章:${commentMailDTO.articleTitle} 收到新评论,已发送邮件通知")
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

}
配置
代码语言:javascript
复制
mail:
    protocol: smtp
    host: smtp.office365.com
    port: 587
    username: shiinamashiro@outlook.com
    password: sakurasou
    properties:
      mail:
#        debug: true
        smtp:
          starttls:
            enable: true
#          socks:
#            host: 127.0.0.1
#            port: 7890

遇到的问题

SMTPSendFailedException: 501 5.1.7 Invalid address

message的from属性设置错误,应为发送者邮箱

451 5.7.3 STARTTLS is required to send mail

Outlook的smtp使用starttls协议,在mail的配置中增加如下:

代码语言:javascript
复制
properties:
      mail:
#        debug: true
        smtp:
          starttls:
            enable: true

参考文章

  1. Java 发送邮件实现(JavaMail 和 Spring 实现)
  2. Spring Boot整合JavaMail实现邮件发送
  3. Spring Boot + Freemarker 中的弯弯绕!
  4. FreeMarker简单入门,这篇就够了
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Spring Mail和FreeMaker发送HTML邮件
    • 引言
      • 实现
        • 环境
        • 依赖
        • 代码
        • 遇到的问题
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档