Spring Boot 使用 JavaMailSender 发送邮件

2021-11-07 From 程序之心 By 丁仪

Spring Boot 是一个及其优秀的框架,帮我们集成了很多常用功能。今天想回顾下如何实现 Java 发送邮件,自然而然地看了下 JavaMail API。查询相关文章的时候,发现 Springboot 已经集成了邮件模块,真是孤陋寡闻了,看来还是应该有空多逛逛开源社区。本文简单记录下 springboot 发送邮件的使用方法。

maven 依赖

springboot 项目直接引入 spring-boot-starter-mail 即可。


   org.springframework.boot
   spring-boot-starter-mail

发个邮件试试

spring 提供的发送接口是 JavaMailSender,使用 springboot 的自动化配置可以大大减轻开发量。在 application.properties 中配置如下。

# SMTP 服务器,换成你的
spring.mail.host=smtp.mxhichina.com
# 邮箱用户名,完整的哦
spring.mail.username=用户名
# 邮箱密码
spring.mail.password=密码
# 身份验证
spring.mail.properties.mail.smtp.auth=true
# 使用 HTTPS
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

然后写个 demo 代码发送一封邮件试试。自动装配引入 JavaMailSender,发送邮件时创建 SimpleMailMessage,输入发件人邮箱地址、收件人邮箱地址、邮件主题、邮件内容,send 发送,搞定。

@Resource
private JavaMailSender javaMailSender;
private void test(){
   SimpleMailMessage message = new SimpleMailMessage();
   message.setFrom("发件人邮箱地址");
   message.setTo("收件人邮箱地址");
   message.setSubject("测试发送一封邮件");
   message.setText("测试邮件内容,啦啦啦");
   javaMailSender.send(message);
}

查看测试的收件人邮箱,邮件已经顺利到达。如丝般顺滑的发送邮件体验。

发送复杂邮件

查看 SimpleMailMessage 的源码,可以看到只能实现简单邮件的发送。设置范围仅限于发件人、收件人、回复人、抄送人、主题、内容等简单的设置。尤其是内容,是个简单的 String 类型。如果需要实现复杂的邮件内容,使用 SimpleMailMessage 比较麻烦。

不怕,还有 MimeMessageHelper。MimeMessageHelper 能够支持模板、附件功能,提供了以下方法:

  • addInline :增加资源,比如图片
  • addAttachment :增加附件;

MimeMessageHelper 的构造器要求传入一个 JavaMail 定义的 MimeMessage 对象,可以直接用 JavaMailSender.createMimeMessage 来创建,避免一些不必要的麻烦。

发送带附件的邮件

addAttachment 支持多种形式的资源,包括 DataSource、File、InputStreamSource。发送带附件的邮件主要分为几个步骤:

1. 使用 javaMailSender 创建 MimeMessage 对象

2. 创建 MimeMessageHelper 对象

3. MimeMessageHelper 设置常规数据

4. MimeMessageHelper 调用 addAttachment 增加附件;

5. 发送邮件;

MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setFrom("发件人邮箱地址");
messageHelper.setTo("收件人邮箱地址");
messageHelper.setSubject("测试发送一封带附件的邮件");
messageHelper.setText("测试邮件附件,哈哈哈");
messageHelper.addAttachment("附件.png", new ClassPathResource("demo.png"));
javaMailSender.send(mimeMessage);

收信效果完全符合预期。

邮件正文嵌入资源

addInline 方法用于在正文中设置行内元素,并用资源的内容替换行内元素,支持 DataSource、File、Resource 多种资源。其中 Resource 是 Spring 定义的资源类型,可以使用 ClassPathResource 等多种实现。

以嵌入图片为例,主要分为几个步骤:

1. 使用 javaMailSender 创建 MimeMessage 对象

2. 创建 MimeMessageHelper 对象

3. MimeMessageHelper 设置常规数据,其中正文需要设置成 HTML 文本,HTML 内使用 cid:demoImage 定义内容id

4. MimeMessageHelper 调用 addInline 增加行内元素的资源,传入内容id demoImage 和资源;

5. 发送邮件;

MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setFrom("发件人邮箱地址");
messageHelper.setTo("收件人邮箱地址");
messageHelper.setSubject("测试发送一封带图片的邮件");
messageHelper.setText("测试邮件嵌入图片,哈哈哈 ", true);
messageHelper.addInline("demoImage", new ClassPathResource("demo.png"));
javaMailSender.send(mimeMessage);

收信效果完全符合预期。查看原文可知,图片是以 base64 方式编码存在原文中。

使用模板发送邮件

如果邮件的内容比较复杂,可以使用 thymeleaf、velocity 等模板引擎来生成邮件内容。可以使用 thymeleaf 的能力生成 HTML 内容。

MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage);
mimeMessageHelper.setFrom("发件人邮箱地址");
mimeMessageHelper.setTo("收件人邮箱地址");
mimeMessageHelper.setSubject("测试邮件");
// 使用 Thymeleaf 模板引擎渲染正文
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setPrefix("");
resolver.setSuffix(".html");
TemplateEngine engine = new TemplateEngine();
engine.setTemplateResolver(resolver);
Context context = new Context();
// 模板变量
context.setVariable("key", "demo");
// 生成正文
String html = engine.process("demo",context);
mimeMessageHelper.setText(html, true);
javaMailSender.send(mimeMessage);

底层实现原理

Spring 提供了 JavaMailSender 接口和 JavaMailSenderImpl 实现类,引入 Spring boot 后,自动完成 bean 注入。因此可以直接自动装配注入 JavaMailSender。

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
class MailSenderPropertiesConfiguration {
  @Bean
  @ConditionalOnMissingBean(JavaMailSender.class)
  JavaMailSenderImpl mailSender(MailProperties properties) {
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    applyProperties(properties, sender);
    return sender;
  }
}

JavaMailSenderImpl 内部封装了 JavaMail 的连接、发送操作。

// something
// 复用 JavaMail 的 Transport
Transport transport = null;
// something
// 连接服务器
transport = connectTransport();
// transport.connect(getHost(), getPort(), username, password);
// something
if (mimeMessage.getSentDate() == null) {
   mimeMessage.setSentDate(new Date());
}
String messageId = mimeMessage.getMessageID();
mimeMessage.saveChanges();
if (messageId != null) {
   mimeMessage.setHeader(HEADER_MESSAGE_ID, messageId);
}
Address[] addresses = mimeMessage.getAllRecipients();
// 发送邮件
transport.sendMessage(mimeMessage, (addresses != null ? addresses : new Address[0]));
// something

本文来源:程序之心,转载请注明出处!

本文地址:https://chengxuzhixin.com/blog/article/300424.html

发表感想

墨渊    2021-11-07 17:37:15    回复

感想分享

© 2016 - 2022 chengxuzhixin.com All Rights Reserved.

浙ICP备2021034854号-1    浙公网安备 33011002016107号