邮件群发工具实验报告
目录
- 一、项目概述
- 二、项目架构
- 三、项目展示
- 3.1 目录结构
- 3.2 主程序(MailBulkSender)
- 3.3 核心业务模块关键逻辑
- 3.3.1 邮件发送核心(MailSender - 批量发送 + 重试)
- 3.3.2 Excel读取核心(ExcelReader - 数据解析)
- 3.3.3 模板渲染核心(TemplateRenderer)
- 3.4 实体类(简化展示)
- 四、运行效果
- 4.1 实际接收邮件
- 4.2 单次邮件发送报告
- 4.3 发送日志
- 五、学习心得
- 六、总结
一、项目概述
本项目是一个基于Java的邮件批量发送工具,通过整合Excel数据读取、模板渲染和邮件发送功能,实现了个性化邮件的批量推送。项目采用模块化设计,核心技术栈包括POI(Excel处理)、JavaMail(邮件发送)、FreeMarker(模板引擎),并通过Maven进行依赖管理,确保开发过程的高效与规范。
核心技术栈在项目中的落地应用
- POI(Apache POI):作为Excel数据解析的核心工具,我通过POI的Workbook、Sheet、Row、Cell等核心类实现了对xlsx格式联系人表格的读取,兼容字符串、数字等不同单元格类型的解析逻辑,精准提取姓名、邮箱、公司等收件人信息,为批量发送提供数据基础。
- JavaMail:是邮件发送功能的核心依赖,我基于JavaMail的Session、MimeMessage、Transport等类封装了邮件发送逻辑,配置SMTP服务器参数(如QQ邮箱的smtp.qq.com、465端口),结合身份认证实现邮件的精准投递,并通过多线程+重试机制提升发送稳定性。
- FreeMarker:用于实现邮件内容的个性化渲染,我将固定邮件模板(email.ftl)与Excel读取的联系人数据结合,通过模板变量(如${name}、${company})动态替换内容,无需硬编码即可生成不同收件人的个性化邮件,大幅提升模板复用性和内容灵活性。
- Maven:作为项目依赖管理工具,我通过pom.xml统一引入POI、JavaMail、FreeMarker等依赖包,自动管理各组件的版本和依赖关系,避免手动导入jar包的冲突问题,保障项目构建和运行的一致性,同时简化了项目的部署和协作流程。
二、项目架构
- 配置初始化:设置邮件服务器参数及发件人信息
- 数据导入:从Excel读取收件人列表
- 模板渲染:结合联系人信息生成个性化邮件内容
- 批量发送:多线程并发发送邮件,带重试机制
- 结果反馈:生成发送报告,统计成功/失败情况
三、项目展示
1.目录结构
2. 主程序(MailBulkSender)
- package com;
- // 省略import
- public class MailBulkSender {
- public static void main(String[] args) {
- try {
- // 1. 配置邮件参数
- MailConfig mailConfig = new MailConfig();
- mailConfig.setSenderEmail("3407645223@qq.com");
- mailConfig.setSenderPassword("lblrwihhllzjdbed");
- mailConfig.setSmtpHost("smtp.qq.com");
- mailConfig.setSmtpPort(465);
- mailConfig.setSslEnable(true);
- // 2. 读取Excel联系人
- ExcelReader excelReader = new ExcelReader();
- List<Contact> contacts = excelReader.readContacts("D:\\homework\\Java/contacts.xlsx");
- System.out.println("读取到联系人数量:" + contacts.size());
- // 3. 初始化发送器并批量发送
- MailSender mailSender = new MailSender(mailConfig);
- String subjectTemplate = "【${company}】尊敬的${name},这是一封个性化测试邮件";
- List<String> attachments = null;
- List<SendLog> logs = mailSender.batchSend(contacts, "email.ftl", subjectTemplate, attachments);
- // 4. 生成发送报告
- mailSender.generateReport(logs, "D:\\homework\\Java/send-report.txt");
- } catch (Exception e) {
- e.printStackTrace();
- System.err.println("群发失败:" + e.getMessage());
- }
- }
- }
复制代码 3. 核心业务模块关键逻辑
(1)邮件发送核心(MailSender - 批量发送 + 重试)
- package com.bulk.sender;
- // 省略import及基础属性定义
- public class MailSender {
- // 核心批量发送逻辑(保留核心流程)
- public List<SendLog> batchSend(List<Contact> contacts, String templateName,
- String subjectTemplate, List<String> attachmentPaths) {
- List<SendLog> logs = new CopyOnWriteArrayList<>();
- ExecutorService executor = Executors.newFixedThreadPool(10); // 线程池控制并发
- for (Contact contact : contacts) {
- SendLog log = new SendLog();
- log.setContact(contact);
- log.setSendTime(new Date());
- logs.add(log);
- executor.submit(() -> {
- int retryCount = 0;
- boolean sendSuccess = false;
- // 失败重试核心逻辑
- while (retryCount < 3 && !sendSuccess) {
- try {
- // 模板变量渲染
- Map<String, Object> dataModel = new HashMap<>();
- dataModel.put("name", contact.getName());
- dataModel.put("company", contact.getCompany());
- String subject = renderSimpleTemplate(subjectTemplate, dataModel);
- String content = new TemplateRenderer().render(templateName, dataModel);
-
- // 发送单封邮件
- sendSingleMail(contact.getEmail(), subject, content, attachmentPaths);
- sendSuccess = true;
- } catch (Exception e) {
- retryCount++;
- // 重试间隔(指数退避)
- try { Thread.sleep(1000 * retryCount); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
- }
- }
- // 更新发送日志
- log.setSuccess(sendSuccess);
- log.setRetryCount(retryCount);
- });
- }
- executor.shutdown();
- return logs;
- }
- // 发送报告生成核心
- public void generateReport(List<SendLog> logs, String reportPath) {
- long successCount = logs.stream().filter(SendLog::isSuccess).count();
- long failCount = logs.size() - successCount;
- // 控制台报告+文件写入核心
- logger.info("===== 邮件发送报告 =====");
- logger.info("总发送数:{} | 成功数:{} | 失败数:{}", logs.size(), successCount, failCount);
- // 省略文件写入细节(保留核心统计逻辑)
- }
- // 省略其他辅助方法
- }
复制代码 (2)Excel 读取核心(ExcelReader - 数据解析)
[code]package com.bulk.reader;// 省略importpublic class ExcelReader { // 核心Excel解析逻辑 public List readContacts(String excelPath) throws Exception { List contacts = new ArrayList(); Workbook workbook = WorkbookFactory.create(new FileInputStream(new File(excelPath))); Sheet sheet = workbook.getSheetAt(0); // 跳过表头读取数据 for (int i = 1; i |