1. 概述

本教程将带你一步步实现在普通 Spring 应用和 Spring Boot 应用中发送邮件。前者使用 JavaMail 库,后者则依赖 spring-boot-starter-mail 依赖。

2. Maven 依赖

首先需要在 pom.xml 中添加依赖。

2.1. Spring 框架

普通 Spring 项目需添加以下依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>6.1.5</version>
</dependency>

最新版本可在 Maven 仓库 查询。

2.2. Spring Boot

Spring Boot 项目添加:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    <version>3.1.5</version>
</dependency>

最新版本见 Maven Central

3. 邮件服务器配置

Spring 框架的邮件支持接口和类组织如下:

  1. MailSender 接口:顶层接口,提供基础邮件发送功能
  2. JavaMailSender 接口MailSender 的子接口,支持 MIME 消息,常与 MimeMessageHelper 配合使用
  3. JavaMailSenderImplJavaMailSender 的实现类,支持 MimeMessageSimpleMailMessage
  4. SimpleMailMessage:用于创建简单邮件(包含发件人、收件人、抄送、主题和正文)
  5. MimeMessagePreparator 接口:MIME 消息准备的回调接口
  6. MimeMessageHelper:创建 MIME 消息的辅助类,支持图片、附件和 HTML 内容

3.1. Spring 邮件配置

通过 JavaMailSenderImpl 指定 SMTP 服务器等属性。Gmail 配置示例:

@Bean
public JavaMailSender getJavaMailSender() {
    JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
    mailSender.setHost("smtp.gmail.com");
    mailSender.setPort(587);
    
    mailSender.setUsername("[email protected]");
    mailSender.setPassword("your-app-password");
    
    Properties props = mailSender.getJavaMailProperties();
    props.put("mail.transport.protocol", "smtp");
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.debug", "true");
    
    return mailSender;
}

3.2. Spring Boot 邮件配置

application.properties 中使用 spring.mail.* 命名空间配置:

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=[email protected]
spring.mail.password=your-app-password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

⚠️ 某些 SMTP 服务器需要 TLS 连接,通过 spring.mail.properties.mail.smtp.starttls.enable 启用。

3.2.1. Gmail SMTP 配置

通过 Gmail SMTP 发送邮件时需注意:

3.2.2. Amazon SES SMTP 配置

使用 Amazon SES 时配置如下:

spring.mail.host=email-smtp.us-west-2.amazonaws.com
spring.mail.username=your-ses-username
spring.mail.password=your-ses-password
spring.mail.properties.mail.transport.protocol=smtp
spring.mail.properties.mail.smtp.port=25
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

⚠️ Amazon 要求先验证凭证,参考 官方指南

4. 发送邮件

配置完成后,使用 JavaMailSender 发送邮件。普通 Spring 和 Spring Boot 的发送方式相同。

4.1. 发送简单邮件

无附件的简单邮件发送示例:

@Component
public class EmailServiceImpl implements EmailService {

    @Autowired
    private JavaMailSender emailSender;

    public void sendSimpleMessage(
      String to, String subject, String text) {
        SimpleMailMessage message = new SimpleMailMessage(); 
        message.setFrom("[email protected]");
        message.setTo(to); 
        message.setSubject(subject); 
        message.setText(text);
        emailSender.send(message);
    }
}

✅ 虽然发件人地址非必填,但多数 SMTP 服务器会拒绝无发件人的邮件。

4.2. 发送带附件邮件

需要发送附件时(如订单确认邮件的发票),使用 MimeMessageHelper

@Override
public void sendMessageWithAttachment(
  String to, String subject, String text, String pathToAttachment) {
    MimeMessage message = emailSender.createMimeMessage();
     
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    
    helper.setFrom("[email protected]");
    helper.setTo(to);
    helper.setSubject(subject);
    helper.setText(text);
        
    FileSystemResource file 
      = new FileSystemResource(new File(pathToAttachment));
    helper.addAttachment("Invoice", file);

    emailSender.send(message);
}

4.3. 邮件模板

SimpleMailMessage 支持字符串格式化,可定义模板 Bean:

@Bean
public SimpleMailMessage templateSimpleMessage() {
    SimpleMailMessage message = new SimpleMailMessage();
    message.setText(
      "这是您的邮件测试模板:\n%s\n");
    return message;
}

使用模板时只需传入参数:

@Autowired
private SimpleMailMessage template;

// ...
String text = String.format(template.getText(), templateArgs);  
sendSimpleMessage(to, subject, text);

5. 处理发送错误

JavaMail 提供 SendFailedException 处理发送失败,但实际使用中可能遇到以下问题:

  1. 异常不会抛出:RFC 821 规定 SMTP 服务器遇到无效地址应返回 550 错误码,但多数公共服务器(如 Gmail)不会抛出异常,而是发送“投递失败”邮件或无反馈
  2. 可选方案
    • 捕获 SendFailedException(但可能永远不会触发)
    • 定期检查发件箱的“投递失败”通知(实现复杂且时间不确定)
    • 若服务器无反馈则无法处理

6. 总结

本文介绍了在 Spring Boot 应用中配置和发送邮件的方法。所有示例代码可在 GitHub 获取。


原始标题:Guide to Spring Email | Baeldung

« 上一篇: Java 中 AI 库介绍
» 下一篇: Guava Multimap使用