ThinkBridge 包中包含了快速发送邮件的代码模块,基于 JavaMail 实现。

仓库坐标

Maven

<dependency>
    <groupId>com.luamas.thinkbridge</groupId>
    <artifactId>mail-spring-boot-starter</artifactId>
</dependency>

Gradle

implementation("com.luamas.thinkbridge:mail-spring-boot-starter")

配置

think:
  app:
    mail:
      # 指定from邮箱
      from: luamas@163.com

spring:
  mail:
    host: smtp.163.com
    port: 465
    username: luamas@163.com
    password: your-password
    properties:
      mail:
        smtp:
          auth: true
          ssl:
            enable: true

发送接口

package com.luamas.thinkbridge.bootstarter.mail.service;

import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public interface EmailService {


    void sendEmail(String from, String[] to, String[] cc, String[] bcc, String subject, String text, Resource[] resources, boolean isHtml) throws Exception;


    default void sendEmail(String[] to, String[] cc, String[] bcc, String subject, String text, Resource[] resources, boolean isHtml) throws Exception {
        this.sendEmail(null, to, cc, bcc, subject, text, resources, isHtml);
    }


    default void sendEmail(String[] to, String[] cc, String[] bcc, String subject, String text, File[] files, boolean isHtml) throws Exception {
        List<Resource> resources = new ArrayList<>();
        Resource[] resourcesArray = null;
        for (File file : files) {
            FileSystemResource fileSystemResource = new FileSystemResource(file);
            resources.add(fileSystemResource);
        }
        if (!resources.isEmpty()) {
            resourcesArray = resources.toArray(new Resource[0]);
        }
        this.sendEmail(to, cc, bcc, subject, text, resourcesArray, isHtml);
    }

    default void sendEmail(String[] to, String[] cc, String[] bcc, String subject, String text, String[] paths, boolean isHtml) throws Exception {
        List<Resource> resources = new ArrayList<>();
        Resource[] resourcesArray = null;
        for (String path : paths) {
            FileSystemResource fileSystemResource = new FileSystemResource(new File(path));
            resources.add(fileSystemResource);
        }
        if (!resources.isEmpty()) {
            resourcesArray = resources.toArray(new Resource[0]);
        }
        this.sendEmail(to, cc, bcc, subject, text, resourcesArray, isHtml);
    }

    /
     * 发送html格式邮件
     *
     * @param to      收件人
     * @param subject 邮件主题
     * @param text    邮件内容
     */
    default void sendHtmlEmail(String[] to, String subject, String text) throws Exception {
        this.sendHtmlEmail(to, null, subject, text);
    }

    /
     * 发送html格式邮件
     *
     * @param to      收件人
     * @param cc      抄送人
     * @param subject 邮件主题
     * @param text    邮件内容
     */
    default void sendHtmlEmail(String[] to, String[] cc, String subject, String text) throws Exception {
        this.sendHtmlEmail(to, cc, null, subject, text);
    }

    /
     * 发送html格式邮件
     *
     * @param to      收件人
     * @param cc      抄送人
     * @param bcc     密抄人
     * @param subject 邮件主题
     * @param text    邮件内容
     */
    default void sendHtmlEmail(String[] to, String[] cc, String[] bcc, String subject, String text) throws Exception {
        this.sendEmail(to, cc, bcc, subject, text, (Resource[]) null, true);
    }


    /
     * 发送html格式邮件
     *
     * @param to        收件人
     * @param subject   邮件主题
     * @param text      邮件内容
     * @param delimiter 分隔符
     */
    default void sendHtmlEmailDelimitedListToStringArray(String to, String subject, String text, String delimiter) throws Exception {
        this.sendHtmlEmailDelimitedListToStringArray(to, null, subject, text, delimiter);
    }

    /
     * 发送html格式邮件
     *
     * @param to        收件人
     * @param cc        抄送人
     * @param subject   邮件主题
     * @param text      邮件内容
     * @param delimiter 分隔符
     */
    default void sendHtmlEmailDelimitedListToStringArray(String to, String cc, String subject, String text, String delimiter) throws Exception {
        this.sendHtmlEmailDelimitedListToStringArray(to, cc, null, subject, text, delimiter);
    }

    /
     * 发送html格式邮件
     *
     * @param to        收件人
     * @param cc        抄送人
     * @param bcc       密抄人
     * @param subject   邮件主题
     * @param text      邮件内容
     * @param delimiter 分隔符
     */
    default void sendHtmlEmailDelimitedListToStringArray(String to, String cc, String bcc, String subject, String text, String delimiter) throws Exception {
        this.sendHtmlEmail(to != null ? StringUtils.delimitedListToStringArray(to, delimiter) : null,
                cc != null ? StringUtils.delimitedListToStringArray(cc, delimiter) : null,
                bcc != null ? StringUtils.delimitedListToStringArray(bcc, delimiter) : null,
                subject, text);
    }


    /
     * 发送html格式邮件
     *
     * @param to        收件人
     * @param subject   邮件主题
     * @param text      邮件内容
     */
    default void sendHtmlEmailCommaDelimitedListToStringArray(String to, String subject, String text) throws Exception {
        this.sendHtmlEmailCommaDelimitedListToStringArray(to, null, subject, text);
    }

    /
     * 发送html格式邮件
     *
     * @param to        收件人
     * @param cc        抄送人
     * @param subject   邮件主题
     * @param text      邮件内容
     */
    default void sendHtmlEmailCommaDelimitedListToStringArray(String to, String cc, String subject, String text) throws Exception {
        this.sendHtmlEmailCommaDelimitedListToStringArray(to, cc, null, subject, text);
    }

    /
     * 发送html格式邮件
     *
     * @param to        收件人
     * @param cc        抄送人
     * @param bcc       密抄人
     * @param subject   邮件主题
     * @param text      邮件内容
     */
    default void sendHtmlEmailCommaDelimitedListToStringArray(String to, String cc, String bcc, String subject, String text) throws Exception {
        this.sendHtmlEmailDelimitedListToStringArray(to, cc, bcc, subject, text, ",");
    }


    /
     * 发送带附件的邮件
     *
     * @param to      收件人
     * @param subject 邮件主题
     * @param text    邮件内容
     * @param paths   附件路径
     */
    default void sendAttachmentsHtmlEmail(String[] to, String subject, String text, String[] paths) throws Exception {
        this.sendAttachmentsHtmlEmail(to, null, subject, text, paths);
    }

    /
     * 发送带附件的邮件
     *
     * @param to      收件人
     * @param cc      抄送人
     * @param subject 邮件主题
     * @param text    邮件内容
     * @param paths   附件路径
     */
    default void sendAttachmentsHtmlEmail(String[] to, String[] cc, String subject, String text, String[] paths) throws Exception {
        this.sendAttachmentsHtmlEmail(to, cc, null, subject, text, paths);
    }

    /
     * 发送带附件的邮件
     *
     * @param to      收件人
     * @param cc      抄送人
     * @param bcc     密抄人
     * @param subject 邮件主题
     * @param text    邮件内容
     * @param paths   附件路径
     */
    default void sendAttachmentsHtmlEmail(String[] to, String[] cc, String[] bcc, String subject, String text, String[] paths) throws Exception {
        this.sendEmail(to, cc, bcc, subject, text, paths, true);
    }
}

示例

package com.luamas.thinkbridge.integration.demo.mail.controller;

import com.luamas.thinkbridge.bootstarter.mail.service.EmailService;
import com.luamas.thinkbridge.common.base.vo.ResponseVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.web.bind.annotation.*;

@Profile("mail")
@Tag(name = "邮件发送")
@RestController
@RequestMapping("mail")
public class MailController {
    @Autowired
    private EmailService emailService;

    @Operation(summary = "发送HTML邮件", description = "发送富文本HTML邮件,支持抄送")
    @GetMapping("send")
    public ResponseVo<Void> send(
            @Parameter(description = "收件人,多个收件人用逗号分隔", example = "luamas@163.com")
            @RequestParam String toSend,
            @Parameter(description = "抄送人,多个抄送人用逗号分隔", example = "cc@163.com")
            @RequestParam(required = false) String toCc,
            @Parameter(description = "邮件标题", example = "ThinkBridge邮件测试")
            @RequestParam String subject,
            @Parameter(description = "邮件HTML内容", example = "<h1>Hello</h1><p>这是一封测试邮件</p>")
            @RequestParam String content) throws Exception {
        emailService.sendHtmlEmail(
                toSend == null ? null : toSend.split(","),
                toCc == null ? null : toCc.split(","),
                subject,
                content);
        return ResponseVo.success();
    }

    @Operation(summary = "发送简单文本邮件", description = "发送纯文本邮件")
    @GetMapping("send-text")
    public ResponseVo<Void> sendText(
            @Parameter(description = "收件人,多个收件人用逗号分隔", example = "luamas@163.com")
            @RequestParam String toSend,
            @Parameter(description = "邮件标题", example = "ThinkBridge文本邮件测试")
            @RequestParam String subject,
            @Parameter(description = "邮件文本内容", example = "这是一封简单的文本邮件")
            @RequestParam String content) throws Exception {
        emailService.sendEmail(
                toSend == null ? null : toSend.split(","),
                null,
                null,
                subject,
                content,
                (String[]) null,
                false);
        return ResponseVo.success();
    }
}
使用 JavaMail,引入 Spring Boot Mail 即可。think.app.mail.from 配置用于指定默认发件人地址。

自定义实现

框架默认提供 EmailServiceImpl 作为 EmailService 的默认实现。ThinkBridgeEmailAutoConfiguration 中 emailService() Bean 使用了 @ConditionalOnMissingBean,当容器中存在自定义的 EmailService 实现时,默认的 EmailServiceImpl 将不会被创建,自动使用自定义实现。

完全替换默认实现

直接实现 EmailService 接口并注册为 Spring Bean,即可完全替换默认的邮件发送逻辑。适用于对接第三方邮件服务、使用自定义邮件模板引擎等场景。

@Slf4j
@Component
public class MyEmailService implements EmailService {

    private final JavaMailSender mailSender;

    public MyEmailService(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    @Override
    public void sendEmail(String from, String[] to, String[] cc, String[] bcc,
                          String subject, String text, Resource[] resources,
                          boolean isHtml) throws Exception {
        // 自定义发送逻辑,例如添加模板渲染、记录日志等
        log.info("使用自定义邮件服务发送邮件: subject={}, to={}", subject, to);
        // ... 自定义实现
    }
}
实现 EmailService 接口时,仅需实现 sendEmail 核心方法,其余 sendHtmlEmail、sendAttachmentsHtmlEmail 等方法均为 default 方法,无需额外实现。

继承扩展默认实现

如需保留默认功能并在此基础上添加自定义逻辑(如发送前后记录日志、邮件内容加密、黑白名单过滤等),可通过继承 EmailServiceImpl 并重写方法来实现。

@Slf4j
@Component
public class MyEmailService extends EmailServiceImpl {

    public MyEmailService(
            @Value("${think.app.mail.from:luamas@163.com}") String from,
            JavaMailSender mailSender) {
        super(from, mailSender);
    }

    @Override
    public void sendEmail(String from, String[] to, String[] cc, String[] bcc,
                          String subject, String text, Resource[] resources,
                          boolean isHtml) throws Exception {
        // 发送前处理
        log.info("邮件发送前处理: subject={}, to={}", subject, to);
        // 邮件内容过滤或加密
        String filteredText = text.replace("敏感词", "*");
        super.sendEmail(from, to, cc, bcc, subject, filteredText, resources, isHtml);
        // 发送后处理
        log.info("邮件发送后处理: 发送成功");
    }
}
继承方式适合在保留原有功能的基础上进行增强,避免重复实现接口中的核心逻辑。如果只需要替换部分行为,继承是最简单的方式。