Java 邮件发送实战:基于 Spring 的微软 EWS 功能封装与复用
·
Java 邮件发送实战:基于 Spring 的微软 EWS 功能封装与复用
1. 核心依赖配置
在 pom.xml 中添加 EWS Java API 依赖:
<dependency>
<groupId>com.microsoft.ews-java-api</groupId>
<artifactId>ews-java-api</artifactId>
<version>2.0</version>
</dependency>
2. EWS 连接配置类
封装 Exchange 服务连接参数:
@Configuration
public class EwsConfig {
@Value("${ews.service.url}") private String serviceUrl;
@Value("${ews.username}") private String username;
@Value("${ews.password}") private String password;
@Bean
public ExchangeService exchangeService() throws Exception {
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.setUrl(new URI(serviceUrl));
service.setCredentials(new WebCredentials(username, password));
return service;
}
}
在 application.properties 配置:
ews.service.url=https://outlook.office365.com/EWS/Exchange.asmx
ews.username=your-email@domain.com
ews.password=your-password
3. 邮件服务封装层
实现可复用的邮件发送组件:
@Service
public class EwsMailService {
private final ExchangeService exchangeService;
public EwsMailService(ExchangeService exchangeService) {
this.exchangeService = exchangeService;
}
/**
* 发送带附件的邮件
* @param to 收件人
* @param subject 主题
* @param body 正文 (支持HTML)
* @param attachments 附件路径列表
*/
public void sendEmailWithAttachments(String to, String subject, String body, List<String> attachments)
throws Exception {
EmailMessage message = new EmailMessage(exchangeService);
message.setSubject(subject);
message.setBody(MessageBody.getMessageBodyFromHtml(body));
message.getToRecipients().add(to);
// 添加附件
for (String filePath : attachments) {
File file = new File(filePath);
message.getAttachments().addFileAttachment(file.getName(), file);
}
message.send();
}
/**
* 发送会议邀请
* @param attendees 参会人邮箱
* @param subject 会议主题
* @param startTime 开始时间
* @param endTime 结束时间
*/
public void sendMeetingInvite(List<String> attendees, String subject,
Date startTime, Date endTime) throws Exception {
Appointment meeting = new Appointment(exchangeService);
meeting.setSubject(subject);
meeting.setStart(startTime);
meeting.setEnd(endTime);
for (String email : attendees) {
meeting.getRequiredAttendees().add(email);
}
meeting.save();
}
}
4. 业务层调用示例
在 Controller 或 Service 中复用封装功能:
@RestController
@RequestMapping("/mail")
public class MailController {
private final EwsMailService mailService;
public MailController(EwsMailService mailService) {
this.mailService = mailService;
}
@PostMapping("/send")
public ResponseEntity<String> sendMail(@RequestBody MailRequest request) {
try {
mailService.sendEmailWithAttachments(
request.getTo(),
request.getSubject(),
request.getBody(),
request.getAttachments()
);
return ResponseEntity.ok("邮件发送成功");
} catch (Exception e) {
return ResponseEntity.status(500).body("发送失败: " + e.getMessage());
}
}
}
5. 高级功能扩展
// 1. 邮件跟踪(已读回执)
message.setIsReadReceiptRequested(true);
// 2. 延迟发送(定时邮件)
message.setExtendedProperty(
new ExtendedPropertyDefinition(
DefaultExtendedPropertySet.Common,
0x0E07,
MapiPropertyType.Boolean
),
true
);
message.setDelayDeliveryMinutes(120); // 延迟2小时
// 3. 邮件分类
message.setCategories(Collections.singletonList("重要通知"));
6. 最佳实践建议
- 连接复用:避免频繁创建
ExchangeService实例,使用连接池管理 - 异常处理:统一捕获
EWSException并转换为业务异常 - 异步发送:使用
@Async注解实现非阻塞发送@Async public void asyncSendEmail(...) { ... } - 模板引擎:集成 Thymeleaf 实现动态邮件模板
Context ctx = new Context(); ctx.setVariable("name", "张三"); String htmlBody = templateEngine.process("welcome.html", ctx);
7. 性能优化方案
// 批量发送时启用分页控制
ItemView view = new ItemView(50); // 每页50条
FindItemsResults<Item> results = service.findItems(folderId, view);
// 使用 NIO 处理大附件
try (FileChannel channel = FileChannel.open(Paths.get(filePath))) {
message.getAttachments().addFileAttachment(
fileName,
channel,
channel.size()
);
}
关键提示:微软已逐步将 EWS 迁移至 Microsoft Graph API,建议新项目直接使用 Microsoft Graph SDK 实现更现代化的集成方案。
更多推荐


所有评论(0)