文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Boot 邮件发送的 5 种姿势

2024-12-11 17:46

关注

邮件发送其实是一个非常常见的需求,用户注册,找回密码等地方,都会用到,使用 JavaSE 代码发送邮件,步骤还是挺繁琐的,Spring Boot 中对于邮件发送,提供了相关的自动化配置类,使得邮件发送变得非常容易,本文我们就来一探究竟!看看使用 Spring Boot 发送邮件的 5 中姿势。

邮件基础

我们经常会听到各种各样的邮件协议,比如 SMTP、POP3、IMAP ,那么这些协议有什么作用,有什么区别?我们先来讨论一下这个问题。

SMTP 是一个基于 TCP/IP 的应用层协议,江湖地位有点类似于 HTTP,SMTP 服务器默认监听的端口号为 25 。看到这里,小伙伴们可能会想到既然 SMTP 协议是基于 TCP/IP 的应用层协议,那么我是不是也可以通过 Socket 发送一封邮件呢?回答是肯定的。

生活中我们投递一封邮件要经过如下几个步骤:

  1. 深圳的小王先将邮件投递到深圳的邮局
  2. 深圳的邮局将邮件运送到上海的邮局
  3. 上海的小张来邮局取邮件

这是一个缩减版的生活中邮件发送过程。这三个步骤可以分别对应我们的邮件发送过程,假设从 aaa@qq.com 发送邮件到 111@163.com :

  1. aaa@qq.com 先将邮件投递到腾讯的邮件服务器
  2. 腾讯的邮件服务器将我们的邮件投递到网易的邮件服务器
  3. 111@163.com 登录网易的邮件服务器查看邮件

邮件投递大致就是这个过程,这个过程就涉及到了多个协议,我们来分别看一下。

SMTP 协议全称为 Simple Mail Transfer Protocol,译作简单邮件传输协议,它定义了邮件客户端软件与 SMTP 服务器之间,以及 SMTP 服务器与 SMTP 服务器之间的通信规则。

也就是说 aaa@qq.com 用户先将邮件投递到腾讯的 SMTP 服务器这个过程就使用了 SMTP 协议,然后腾讯的 SMTP 服务器将邮件投递到网易的 SMTP 服务器这个过程也依然使用了 SMTP 协议,SMTP 服务器就是用来收邮件。

而 POP3 协议全称为 Post Office Protocol ,译作邮局协议,它定义了邮件客户端与 POP3 服务器之间的通信规则,那么该协议在什么场景下会用到呢?当邮件到达网易的 SMTP 服务器之后, 111@163.com 用户需要登录服务器查看邮件,这个时候就该协议就用上了:邮件服务商都会为每一个用户提供专门的邮件存储空间,SMTP 服务器收到邮件之后,就将邮件保存到相应用户的邮件存储空间中,如果用户要读取邮件,就需要通过邮件服务商的 POP3 邮件服务器来完成。

最后,可能也有小伙伴们听说过 IMAP 协议,这个协议是对 POP3 协议的扩展,功能更强,作用类似,这里不再赘述。

准备工作

目前国内大部分的邮件服务商都不允许直接使用用户名/密码的方式来在代码中发送邮件,都是要先申请授权码,这里以 QQ 邮箱为例,向大家演示授权码的申请流程:首先我们需要先登录 QQ 邮箱网页版,点击上方的设置按钮:

p266

 

然后点击账户选项卡:

p267

 

在账户选项卡中找到开启POP3/SMTP选项,如下:

p268

 

点击开启,开启相关功能,开启过程需要手机号码验证,按照步骤操作即可,不赘述。开启成功之后,即可获取一个授权码,将该号码保存好,一会使用。

项目创建

接下来,我们就可以创建项目了,Spring Boot 中,对于邮件发送提供了自动配置类,开发者只需要加入相关依赖,然后配置一下邮箱的基本信息,就可以发送邮件了。

首先创建一个 Spring Boot 项目,引入邮件发送依赖:

 

创建完成后,项目依赖如下:

  1.  
  2.     org.springframework.boot 
  3.     spring-boot-starter-mail 
  4.  
  5.  
  6.     org.springframework.boot 
  7.     spring-boot-starter-web 
  8.  

项目创建成功后,接下来在 application.properties 中配置邮箱的基本信息:

  1. spring.mail.host=smtp.qq.com 
  2. spring.mail.port=587 
  3. spring.mail.username=1510161612@qq.com 
  4. spring.mail.password=ubknfzhjkhrbbabe 
  5. spring.mail.default-encoding=UTF-8 
  6. spring.mail.properties.mail.smtp.socketFactoryClass=javax.net.ssl.SSLSocketFactory 
  7. spring.mail.properties.mail.debug=true 

配置含义分别如下:

如果不知道 smtp 服务器的端口或者地址的的话,可以参考 腾讯的邮箱文档

做完这些之后,Spring Boot 就会自动帮我们配置好邮件发送类,相关的配置在 org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration 类中,部分源码如下:

  1. @Configuration 
  2. @ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class }) 
  3. @ConditionalOnMissingBean(MailSender.class) 
  4. @Conditional(MailSenderCondition.class) 
  5. @EnableConfigurationProperties(MailProperties.class) 
  6. @Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class }) 
  7. public class MailSenderAutoConfiguration { 

从这段代码中,可以看到,导入了另外一个配置 MailSenderPropertiesConfiguration 类,这个类中,提供了邮件发送相关的工具类:

  1. @Configuration 
  2. @ConditionalOnProperty(prefix = "spring.mail"name = "host"
  3. class MailSenderPropertiesConfiguration { 
  4.         private final MailProperties properties; 
  5.         MailSenderPropertiesConfiguration(MailProperties properties) { 
  6.                 this.properties = properties; 
  7.         } 
  8.         @Bean 
  9.         @ConditionalOnMissingBean 
  10.         public JavaMailSenderImpl mailSender() { 
  11.                 JavaMailSenderImpl sender = new JavaMailSenderImpl(); 
  12.                 applyProperties(sender); 
  13.                 return sender; 
  14.         } 

可以看到,这里创建了一个 JavaMailSenderImpl 的实例, JavaMailSenderImpl 是 JavaMailSender 的一个实现,我们将使用 JavaMailSenderImpl 来完成邮件的发送工作。

做完如上两步,邮件发送的准备工作就算是完成了,接下来就可以直接发送邮件了。

具体的发送,有 5 种不同的方式,我们一个一个来看。

发送简单邮件

简单邮件就是指邮件内容是一个普通的文本文档:

  1. @Autowired 
  2. JavaMailSender javaMailSender; 
  3. @Test 
  4. public void sendSimpleMail() { 
  5.     SimpleMailMessage message = new SimpleMailMessage(); 
  6.     message.setSubject("这是一封测试邮件"); 
  7.     message.setFrom("1510161612@qq.com"); 
  8.     message.setTo("25xxxxx755@qq.com"); 
  9.     message.setCc("37xxxxx37@qq.com"); 
  10.     message.setBcc("14xxxxx098@qq.com"); 
  11.     message.setSentDate(new Date()); 
  12.     message.setText("这是测试邮件的正文"); 
  13.     javaMailSender.send(message); 

从上往下,代码含义分别如下:

  1. 构建一个邮件对象
  2. 设置邮件主题
  3. 设置邮件发送者
  4. 设置邮件接收者,可以有多个接收者
  5. 设置邮件抄送人,可以有多个抄送人
  6. 设置隐秘抄送人,可以有多个
  7. 设置邮件发送日期
  8. 设置邮件的正文
  9. 发送邮件

最后执行该方法,就可以实现邮件的发送,发送效果图如下:

 

发送带附件的邮件

邮件的附件可以是图片,也可以是普通文件,都是支持的。

  1. @Test 
  2. public void sendAttachFileMail() throws MessagingException { 
  3.     MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 
  4.     MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true); 
  5.     helper.setSubject("这是一封测试邮件"); 
  6.     helper.setFrom("1510161612@qq.com"); 
  7.     helper.setTo("25xxxxx755@qq.com"); 
  8.     helper.setCc("37xxxxx37@qq.com"); 
  9.     helper.setBcc("14xxxxx098@qq.com"); 
  10.     helper.setSentDate(new Date()); 
  11.     helper.setText("这是测试邮件的正文"); 
  12.     helper.addAttachment("javaboy.jpg",new File("C:\\Users\\sang\\Downloads\\javaboy.png")); 
  13.     javaMailSender.send(mimeMessage); 

注意这里在构建邮件对象上和前文有所差异,这里是通过 javaMailSender 来获取一个复杂邮件对象,然后再利用 MimeMessageHelper 对邮件进行配置,MimeMessageHelper 是一个邮件配置的辅助工具类,创建时候的 true 表示构建一个 multipart message 类型的邮件,有了 MimeMessageHelper 之后,我们针对邮件的配置都是由 MimeMessageHelper 来代劳。

最后通过 addAttachment 方法来添加一个附件。

执行该方法,邮件发送效果图如下:

 

发送带图片资源的邮件

图片资源和附件有什么区别呢?图片资源是放在邮件正文中的,即一打开邮件,就能看到图片。但是一般来说,不建议使用这种方式,一些公司会对邮件内容的大小有限制(因为这种方式是将图片一起发送的)。

  1. @Test 
  2. public void sendImgResMail() throws MessagingException { 
  3.     MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 
  4.     MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 
  5.     helper.setSubject("这是一封测试邮件"); 
  6.     helper.setFrom("1510161612@qq.com"); 
  7.     helper.setTo("25xxxxx755@qq.com"); 
  8.     helper.setCc("37xxxxx37@qq.com"); 
  9.     helper.setBcc("14xxxxx098@qq.com"); 
  10.     helper.setSentDate(new Date()); 
  11.     helper.setText("

    hello 大家好,这是一封测试邮件,这封邮件包含两种图片,分别如下

    第一张图片:

    第二张图片:

    "
    ,true); 
  12.     helper.addInline("p01",new FileSystemResource(new File("C:\\Users\\sang\\Downloads\\javaboy.png"))); 
  13.     helper.addInline("p02",new FileSystemResource(new File("C:\\Users\\sang\\Downloads\\javaboy2.png"))); 
  14.     javaMailSender.send(mimeMessage); 

 

这里的邮件 text 是一个 HTML 文本,里边涉及到的图片资源先用一个占位符占着,setText 方法的第二个参数 true 表示第一个参数是一个 HTML 文本。

setText 之后,再通过 addInline 方法来添加图片资源。

最后执行该方法,发送邮件,效果如下:

 

在公司实际开发中,第一种和第三种都不是使用最多的邮件发送方案。因为正常来说,邮件的内容都是比较的丰富的,所以大部分邮件都是通过 HTML 来呈现的,如果直接拼接 HTML 字符串,这样以后不好维护,为了解决这个问题,一般邮件发送,都会有相应的邮件模板。最具代表性的两个模板就是 Freemarker 模板和 Thyemeleaf 模板了。

使用 Freemarker 作邮件模板

首先需要引入 Freemarker 依赖:

  1.  
  2.     org.springframework.boot 
  3.     spring-boot-starter-freemarker 
  4.  

然后在 resources/templates 目录下创建一个 mail.ftl 作为邮件发送模板:

  1.  
  2. "en"
  3.  
  4.     "UTF-8"
  5.     Title 
  6.  
  7.  
  8. hello 欢迎加入 xxx 大家庭,您的入职信息如下:

     
  9. <table border="1"
  10.      
  11.         姓名 
  12.         ${username} 
  13.      
  14.      
  15.         工号 
  16.         ${num} 
  17.      
  18.      
  19.         薪水 
  20.         ${salary} 
  21.      
  22. table
  23. "color: #ff1a0e">一起努力创造辉煌
 
  •  
  •  
  •  

    接下来,将邮件模板渲染成 HTML ,然后发送即可。

    1. @Test 
    2. public void sendFreemarkerMail() throws MessagingException, IOException, TemplateException { 
    3.     MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 
    4.     MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 
    5.     helper.setSubject("这是一封测试邮件"); 
    6.     helper.setFrom("1510161612@qq.com"); 
    7.     helper.setTo("25xxxxx755@qq.com"); 
    8.     helper.setCc("37xxxxx37@qq.com"); 
    9.     helper.setBcc("14xxxxx098@qq.com"); 
    10.     helper.setSentDate(new Date()); 
    11.     //构建 Freemarker 的基本配置 
    12.     Configuration configuration = new Configuration(Configuration.VERSION_2_3_0); 
    13.     // 配置模板位置 
    14.     ClassLoader loader = MailApplication.class.getClassLoader(); 
    15.     configuration.setClassLoaderForTemplateLoading(loader, "templates"); 
    16.     //加载模板 
    17.     Template template = configuration.getTemplate("mail.ftl"); 
    18.     User user = new User(); 
    19.     user.setUsername("javaboy"); 
    20.     user.setNum(1); 
    21.     user.setSalary((double) 99999); 
    22.     StringWriter out = new StringWriter(); 
    23.     //模板渲染,渲染的结果将被保存到 out 中 ,将out 中的 html 字符串发送即可 
    24.     template.process(userout); 
    25.     helper.setText(out.toString(),true); 
    26.     javaMailSender.send(mimeMessage); 

    需要注意的是,虽然引入了 Freemarker 的自动化配置,但是我们在这里是直接 new Configuration 来重新配置 Freemarker 的,所以 Freemarker 默认的配置这里不生效,因此,在填写模板位置时,值为 templates 。

    调用该方法,发送邮件,效果图如下:

     

    使用 Thymeleaf 作邮件模板

    推荐在 Spring Boot 中使用 Thymeleaf 来构建邮件模板。因为 Thymeleaf 的自动化配置提供了一个 TemplateEngine,通过 TemplateEngine 可以方便的将 Thymeleaf 模板渲染为 HTML ,同时,Thymeleaf 的自动化配置在这里是继续有效的 。

    首先,引入 Thymeleaf 依赖:

    1.  
    2.     org.springframework.boot 
    3.     spring-boot-starter-thymeleaf 
    4.  

    然后,创建 Thymeleaf 邮件模板:

    1.  
    2. "en" xmlns:th="http://www.thymeleaf.org"
    3.  
    4.     "UTF-8"
    5.     Title 
    6.  
    7.  
    8. hello 欢迎加入 xxx 大家庭,您的入职信息如下:

       
    9. <table border="1"
    10.      
    11.         姓名 
    12.         "${username}"
    13.      
    14.      
    15.         工号 
    16.         "${num}"
    17.      
    18.      
    19.         薪水 
    20.         "${salary}"
    21.      
    22. table
    23. "color: #ff1a0e">一起努力创造辉煌
     
  •  
  •  
  •  

    接下来发送邮件:

    1. @Autowired 
    2. TemplateEngine templateEngine; 
    3.  
    4. @Test 
    5. public void sendThymeleafMail() throws MessagingException { 
    6.     MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 
    7.     MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 
    8.     helper.setSubject("这是一封测试邮件"); 
    9.     helper.setFrom("1510161612@qq.com"); 
    10.     helper.setTo("25xxxxx755@qq.com"); 
    11.     helper.setCc("37xxxxx37@qq.com"); 
    12.     helper.setBcc("14xxxxx098@qq.com"); 
    13.     helper.setSentDate(new Date()); 
    14.     Context context = new Context(); 
    15.     context.setVariable("username""javaboy"); 
    16.     context.setVariable("num","000001"); 
    17.     context.setVariable("salary""99999"); 
    18.     String process = templateEngine.process("mail.html", context); 
    19.     helper.setText(process,true); 
    20.     javaMailSender.send(mimeMessage); 

    调用该方法,发送邮件,效果图如下:

     

    好了,这就是我们今天说的 5 种邮件发送姿势,不知道你掌握了没有呢?

     

    本文案例已经上传到 GitHub:https://github.com/lenve/javaboy-code-samples。

    本文转载自微信公众号「江南一点雨」,可以通过以下二维码关注。转载本文请联系江南一点雨公众号。

     

    来源:江南一点雨 内容投诉

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    软考中级精品资料免费领

    • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

      难度     813人已做
      查看
    • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

      难度     354人已做
      查看
    • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

      难度     318人已做
      查看
    • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

      难度     435人已做
      查看
    • 2024年上半年系统架构设计师考试综合知识真题

      难度     224人已做
      查看

    相关文章

    发现更多好内容

    猜你喜欢

    AI推送时光机
    位置:首页-资讯-后端开发
    咦!没有更多了?去看看其它编程学习网 内容吧
    首页课程
    资料下载
    问答资讯