Appearance
Spring Integration 邮件支持教程
专为初学者设计,使用 Kotlin 与注解配置,避免 XML 配置
一、邮件支持概述
Spring Integration 邮件模块提供无缝集成邮件服务的能力:
- 📤 发送邮件:通过
MailSendingMessageHandler
将消息转换为邮件 - 📥 接收邮件:通过
MailReceivingMessageSource
监听邮箱消息 - 🔄 协议支持:完整支持 POP3/IMAP 协议及高级特性(如 IDLE 监听)
核心应用场景
- 系统告警邮件自动发送
- 用户注册验证码邮件处理
- 邮箱订单信息自动化处理系统
二、基础依赖配置
在 build.gradle.kts
中添加依赖:
kotlin
dependencies {
implementation("org.springframework.integration:spring-integration-mail:6.5.1")
implementation("com.sun.mail:jakarta.mail:2.0.1") // 邮件协议实现
}
关键注意事项
必须同时添加 jakarta.mail-api
和具体实现(如 com.sun.mail
),否则运行时将报错
三、发送邮件适配器
使用 MailSendingMessageHandler
发送邮件:
1. 基础配置
kotlin
@Configuration
class MailConfig {
@Bean
fun mailSender(): JavaMailSender {
return JavaMailSenderImpl().apply {
host = "smtp.example.com"
port = 587
username = "user@example.com"
password = "password"
javaMailProperties = Properties().apply {
put("mail.smtp.auth", "true")
put("mail.smtp.starttls.enable", "true")
}
}
}
@Bean
fun mailSendingAdapter() = IntegrationFlow { flow ->
flow.handle(Mail.outboundAdapter(mailSender()))
}
}
2. 发送带动态内容的邮件
kotlin
@Service
class OrderService(
private val messagingTemplate: MessagingTemplate
) {
fun sendOrderConfirmation(email: String, orderId: String) {
val message = MessageBuilder.withPayload("")
.setHeader(MailHeaders.SUBJECT, "订单确认 - $orderId")
.setHeader(MailHeaders.TO, email)
.build()
messagingTemplate.send("mailSendingChannel", message)
}
}
邮件头部常量说明
kotlin
// 可用头部控制字段:
MailHeaders.SUBJECT // 邮件主题
MailHeaders.TO // 收件人
MailHeaders.CC // 抄送
MailHeaders.BCC // 密送
MailHeaders.FROM // 发件人
MailHeaders.REPLY_TO // 回复地址
四、接收邮件适配器
支持 主动轮询 和 事件驱动 两种模式:
1. IMAP IDLE 监听(事件驱动)
kotlin
@Bean
fun imapIdleAdapter(): IntegrationFlow {
return IntegrationFlow.from(
Mail.imapIdleAdapter("imaps://user:pwd@imap.example.com/INBOX")
.autoStartup(true)
.shouldMarkMessagesAsRead(true) // // 标记为已读
.javaMailProperties(Properties().apply {
put("mail.imap.ssl.enable", "true")
})
.get()
).channel(MessageChannels.queue("inboundEmails"))
.get()
}
2. 邮件过滤(仅处理重要邮件)
kotlin
@Bean
fun filteredImapAdapter(): IntegrationFlow {
return IntegrationFlow.from(
Mail.imapInboundAdapter("imaps://user:pwd@imap.example.com/INBOX")
.mailFilterExpression("subject matches '(?i).*URGENT.*'") // [!code highlight] // 过滤主题包含 URGENT 的邮件
.get()
).handle { message ->
println("收到紧急邮件: ${message.payload}")
}.get()
}
协议选择建议
- 📨 IMAP:需要实时监听时使用(支持 IDLE)
- 📭 POP3:仅需定时收取邮件时使用
五、邮件消息解析
Spring 自动映射邮件元数据到消息头:
关键头部字段说明:
头部字段 | 说明 | 示例值 |
---|---|---|
mail_subject | 邮件主题 | 订单确认 #12345 |
mail_from | 发件人地址 | noreply@example.com |
mail_receivedDate | 接收时间 | 2024-06-15T10:30:00Z |
mail_contentType | 内容类型 | text/plain; charset=UTF-8 |
六、事务与错误处理
确保邮件处理可靠性:
1. 事务同步配置
kotlin
@Bean
fun transactionalFlow(): IntegrationFlow {
return IntegrationFlow.from(
Mail.imapInboundAdapter("imaps://user:pwd@imap.example.com/INBOX")
.get()
).transactional(DefaultTransactionManager()) // [!code highlight] // 启用事务
.handle { message ->
// 业务处理...
}.get()
}
2. 异常处理策略
kotlin
@Bean
fun errorHandlingFlow(): IntegrationFlow {
return IntegrationFlow.from("receiveChannel")
.handle(Mail.outboundAdapter(mailSender())) { endpoint ->
endpoint.advice(expressionAdvice()) // [!code highlight] // 添加异常处理
}.get()
}
fun expressionAdvice() = ExpressionEvaluatingRequestHandlerAdvice().apply {
onFailureExpression = "@mailErrorService.handle(#root)" // [!code highlight] // 失败时调用服务
}
连接丢失风险
IMAP IDLE 长连接可能因网络问题中断,建议:
- 配置
mail.imap.timeout=300000
(5分钟超时) - 实现重连机制
七、最佳实践总结
✅ 推荐实践
kotlin
// 使用 DSL 配置完整流程
@Bean
fun mailProcessingFlow(): IntegrationFlow {
return IntegrationFlow
.from(Mail.imapIdleAdapter("imaps://user:pwd@imap.example.com/INBOX"))
.filter(HeaderMailFilter("subject", "(?i).*CONFIRM.*"))
.transform(Mail.toStringTransformer()) // [!code highlight] // 转换为字符串
.handle("orderService", "processOrder")
.get()
}
❌ 应避免的做法
kotlin
// 错误示例:未处理多部分邮件
@Bean
fun riskyFlow(): IntegrationFlow {
return IntegrationFlow
.from(Mail.pop3InboundAdapter("pop3://..."))
.handle { message ->
// 直接处理 MimeMessage 可能导致内容解析错误
}
}
性能优化技巧
- 对带附件的邮件设置
autoCloseFolder=false
保持连接 - 使用
shouldMarkMessagesAsRead=false
避免重复处理 - 对大量邮件使用分页处理