全栈开发之SpringBoot发送邮件

简介: 全栈开发之SpringBoot发送邮件

背景


发送邮件的场景:用户注册验证、忘记密码验证、监控告警、信息推送等。

这里以发送邮箱验证码为例,演示 SpringBoot 集成发送邮件的各种方法:


  1. 普通文本邮件
  2. HTML富文本邮件
  3. 带附件邮件
  4. 内联静态图片邮件
  5. HTML模板邮件


获取授权码


在通过程序集成邮件服务之前,需要到各邮箱服务提供商处获取授权码,这里以QQ邮箱为例。


QQ邮箱-->设置-->账户-->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务-->开启POP3/SMTP服务,按照指示发送短信便可以获取QQ邮箱的授权码

image.png


基础配置


包括 pom 依赖与 yml 配置。


POM依赖


<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--email-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <!--模板引擎-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>


配置


spring:
  mail:
    host: smtp.qq.com
    username: 你的邮箱
    password: 你的授权码
    properties:
      mail:
        smpt:
          auth: true
          starttls:
            enable: true
            required: true


发送邮件


在发送邮件之前,我们先写一个接口模拟生成验证码,接下来就以发送邮箱验证码为例来演示。


生成验证码


public String getCode() {
        String str = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // no zero
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int index = (int) (Math.random() * str.length());
            code.append(str.charAt(index));
        }
        return code.toString();
    }

image.png


普通文本邮件


一般集成发送邮件服务,使用发送普通文本的邮件就足够了。

@Value("${spring.mail.username}")
    private String mailSender;
    @Autowired
    private JavaMailSender javaMailSender;
    @PostMapping("text")
    public String sendTextMail(@RequestParam String target) {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(mailSender);
        mailMessage.setTo(target);
        mailMessage.setSubject("XY平台注册验证码邮件");
        String code = getCode();
        mailMessage.setText("您的验证码为: " + code
                + "(有效期5分钟)。为了保证您的帐户安全,请勿向任何人提供此验证码。本邮件由系统自动发送,请勿直接回复。");
        javaMailSender.send(mailMessage);
        return code;
    }

image.png


HTML富文本邮件


HTML富文本邮件的方式可以使用各种基本的CSS样式。

@PostMapping("html")
    public String sendHTMLMail(@RequestParam String target) throws MessagingException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
        mimeMessageHelper.setFrom(mailSender);
        mimeMessageHelper.setTo(target);
        mimeMessageHelper.setSubject("XY平台注册验证码邮件");
        String code = getCode();
        String sb = "<h2>您的验证码为:</h2>" +
                "<p style='color:red; text-align:center'> " + code + "(有效期5分钟)</p>" +
                "<p style='font-weight:bold; text-decoration:underline'>为了保证您的帐户安全,请勿向任何人提供此验证码。本邮件由系统自动发送,请勿直接回复。</p>";
        mimeMessageHelper.setText(sb, true); // 关键是第二个参数,开启将富文本渲染为HTML
        javaMailSender.send(mimeMessage);
        return code;
    }

image.png


带附件邮件


我这里在资源目录中放了一张图片,作为邮件附件进行传输。

@PostMapping("attachment")
    public String sendAttachmentMail(@RequestParam String target) throws MessagingException, IOException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
        mimeMessageHelper.setFrom(mailSender);
        mimeMessageHelper.setTo(target);
        mimeMessageHelper.setSubject("XY平台注册验证码邮件");
        String code = getCode();
        mimeMessageHelper.setText("您的验证码为: " + code
                + "(有效期5分钟)。为了保证您的帐户安全,请勿向任何人提供此验证码。本邮件由系统自动发送,请勿直接回复。"); // 关键是第二个参数,开启将富文本渲染为HTML
        // 附件
        String fileName = "avatar.jpg";
        Resource resource = new ClassPathResource(fileName);
        mimeMessageHelper.addAttachment(fileName, resource.getFile());
        javaMailSender.send(mimeMessage);
        return code;
    }

image.png


内联静态图片邮件


@PostMapping("inline")
    public String sendInlineMail(@RequestParam String target) throws MessagingException, IOException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
        mimeMessageHelper.setFrom(mailSender);
        mimeMessageHelper.setTo(target);
        mimeMessageHelper.setSubject("XY平台注册验证码邮件");
        String code = getCode();
        String resourceId = "avatar"; // 每个资源对应一个ID
        String sb = "<h2>您的验证码为:</h2>" +
                "<p style='color:red; text-align:center'> " + code + "(有效期5分钟)</p>" +
                "<img style='width:64px; height:64px;' src='cid:" + resourceId + "' />" +
                "<p style='font-weight:bold; text-decoration:underline'>为了保证您的帐户安全,请勿向任何人提供此验证码。本邮件由系统自动发送,请勿直接回复。</p>";
        mimeMessageHelper.setText(sb, true); // 关键是第二个参数,开启将富文本渲染为HTML
        // 内联静态资源
        String fileName = "avatar.jpg";
        Resource resource = new ClassPathResource(fileName);
        mimeMessageHelper.addInline(resourceId, resource.getFile());
        javaMailSender.send(mimeMessage);
        return code;
    }

image.png


HTML模板邮件


这是最为放飞自我的发送邮件的方式了,可以使用各种高大上的设计;此处用到了模板引擎 Thymleaf

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h2 th:text="|尊敬的${username} :|"></h2><br />
    <img src="https://avatars.githubusercontent.com/u/8071981?s=40&v=4" /> 您有服务运行异常。<a th:href="${url}">查看详情</a>
    <br />
</body>
</html>
@Autowired
    private TemplateEngine templateEngine;
    @PostMapping("template")
    public String sendTemplateMail(@RequestParam String target) throws MessagingException, IOException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
        mimeMessageHelper.setFrom(mailSender);
        mimeMessageHelper.setTo(target);
        mimeMessageHelper.setSubject("HTML模板邮件");
        // HTML 模板
        Context context = new Context();
        context.setVariable("username", "HeartSuit");
        context.setVariable("url", "https://avatars.githubusercontent.com/u/8071981?s=40&v=4");
        String content = templateEngine.process("notify", context);
        mimeMessageHelper.setText(content, true); // 关键是第二个参数,开启将富文本渲染为HTML
        javaMailSender.send(mimeMessage);
        return "OK";
    }

image.png

这让我想起了之前使用 Spring Boot Admin 对服务监控的邮件告警推送时的场景:

  • 邮件通知使用的模板存放在 server 依赖的 classpath:/META-INF/spring-boot-admin-server/mail/status-changed.html 路径;
  • 如果想要自定义模板内容,可以拷贝这个文件放到自己的 templates 目录下,修改成自己想要的效果,然后在配置中指定自定义模板路径。
spring:
  boot:
    admin:
      notify:
        mail:
          # 自定义邮件模版
          template: classpath:/templates/notify.html


测试接口


这里直接使用 IDEA 的插件 RESTfulToolkit 进行测试。

http://localhost:8080/mail/text
http://localhost:8080/mail/html
http://localhost:8080/mail/attachment
http://localhost:8080/mail/inline
http://localhost:8080/mail/template
http://localhost:8080/mail/code

以上测试地址,分别对应普通文本邮件,HTML富文本邮件,带附件邮件,内联静态图片邮件,HTML模板邮件以及生成验证码接口。


目录
相关文章
|
9月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
579 7
|
9月前
|
人工智能 Java 数据库
飞算 JavaAI:革新电商订单系统 Spring Boot 微服务开发
在电商订单系统开发中,传统方式耗时约30天,需应对复杂代码、调试与测试。飞算JavaAI作为一款AI代码生成工具,专注于简化Spring Boot微服务开发。它能根据业务需求自动生成RESTful API、数据库交互及事务管理代码,将开发时间缩短至1小时,效率提升80%。通过减少样板代码编写,提供规范且准确的代码,飞算JavaAI显著降低了开发成本,为软件开发带来革新动力。
|
10月前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
892 79
|
8月前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
703 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
7月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
840 0
|
10月前
|
人工智能 自然语言处理 前端开发
20分钟上手DeepSeek开发:SpringBoot + Vue2快速构建AI对话系统
本文介绍如何使用Spring Boot3与Vue2快速构建基于DeepSeek的AI对话系统。系统具备实时流式交互、Markdown内容渲染、前端安全防护等功能,采用响应式架构提升性能。后端以Spring Boot为核心,结合WebFlux和Lombok开发;前端使用Vue2配合WebSocket实现双向通信,并通过DOMPurify保障安全性。项目支持中文语义优化,API延迟低,成本可控,适合个人及企业应用。跟随教程,轻松开启AI应用开发之旅!
|
12月前
|
监控 Java 应用服务中间件
SpringBoot是如何简化Spring开发的,以及SpringBoot的特性以及源码分析
Spring Boot 通过简化配置、自动配置和嵌入式服务器等特性,大大简化了 Spring 应用的开发过程。它通过提供一系列 `starter` 依赖和开箱即用的默认配置,使开发者能够更专注于业务逻辑而非繁琐的配置。Spring Boot 的自动配置机制和强大的 Actuator 功能进一步提升了开发效率和应用的可维护性。通过对其源码的分析,可以更深入地理解其内部工作机制,从而更好地利用其特性进行开发。
491 6
|
12月前
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
332 5
|
12月前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
584 2
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
461 13