邮件群发工具实验报告

邮件群发工具实验报告

目录

一、项目概述

本项目是一个基于Java的邮件批量发送工具,通过整合Excel数据读取、模板渲染和邮件发送功能,实现了个性化邮件的批量推送。项目采用模块化设计,核心技术栈包括POI(Excel处理)、JavaMail(邮件发送)、FreeMarker(模板引擎),并通过Maven进行依赖管理,确保开发过程的高效与规范。

核心技术栈在项目中的落地应用

  1. POI(Apache POI):作为Excel数据解析的核心工具,我通过POI的WorkbookSheetRowCell等核心类实现了对xlsx格式联系人表格的读取,兼容字符串、数字等不同单元格类型的解析逻辑,精准提取姓名、邮箱、公司等收件人信息,为批量发送提供数据基础。
  2. JavaMail:是邮件发送功能的核心依赖,我基于JavaMail的SessionMimeMessageTransport等类封装了邮件发送逻辑,配置SMTP服务器参数(如QQ邮箱的smtp.qq.com、465端口),结合身份认证实现邮件的精准投递,并通过多线程+重试机制提升发送稳定性。
  3. FreeMarker:用于实现邮件内容的个性化渲染,我将固定邮件模板(email.ftl)与Excel读取的联系人数据结合,通过模板变量(如${name}、${company})动态替换内容,无需硬编码即可生成不同收件人的个性化邮件,大幅提升模板复用性和内容灵活性。
  4. Maven:作为项目依赖管理工具,我通过pom.xml统一引入POI、JavaMail、FreeMarker等依赖包,自动管理各组件的版本和依赖关系,避免手动导入jar包的冲突问题,保障项目构建和运行的一致性,同时简化了项目的部署和协作流程。

二、项目架构

  1. 配置初始化:设置邮件服务器参数及发件人信息
  2. 数据导入:从Excel读取收件人列表
  3. 模板渲染:结合联系人信息生成个性化邮件内容
  4. 批量发送:多线程并发发送邮件,带重试机制
  5. 结果反馈:生成发送报告,统计成功/失败情况

三、项目展示

1.目录结构

屏幕截图 2025-12-23 185154

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 - 数据解析)

package com.bulk.reader;

// 省略import

public class ExcelReader {
    // 核心Excel解析逻辑
    public List<Contact> readContacts(String excelPath) throws Exception {
        List<Contact> contacts = new ArrayList<>();
        Workbook workbook = WorkbookFactory.create(new FileInputStream(new File(excelPath)));
        Sheet sheet = workbook.getSheetAt(0);

        // 跳过表头读取数据
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            if (row == null) continue;

            Contact contact = new Contact();
            contact.setName(getCellValue(row.getCell(0))); // 姓名
            contact.setEmail(getCellValue(row.getCell(1))); // 邮箱
            contact.setCompany(getCellValue(row.getCell(2))); // 公司

            if (contact.getEmail() != null && !contact.getEmail().isEmpty()) {
                contacts.add(contact);
            }
        }
        workbook.close();
        return contacts;
    }

    // 单元格值统一处理核心
    private String getCellValue(Cell cell) {
        if (cell == null) return "";
        switch (cell.getCellType()) {
            case STRING: return cell.getStringCellValue().trim();
            case NUMERIC: return String.valueOf(cell.getNumericCellValue()).trim();
            default: return "";
        }
    }
}

(3)模板渲染核心(TemplateRenderer)

package com.bulk.renderer;

// 省略import

public class TemplateRenderer {
    // 核心模板渲染逻辑
    public String render(String templateName, Map<String, Object> dataModel) throws Exception {
        Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_32);
        freemarkerConfig.setClassForTemplateLoading(this.getClass(), "/templates");
        Template template = freemarkerConfig.getTemplate(templateName);
        StringWriter writer = new StringWriter();
        template.process(dataModel, writer); // 核心模板渲染
        return writer.toString();
    }
}

4.实体类(简化展示)

// Contact实体
package com.bulk.entity;
public class Contact {
    private String name;      // 姓名
    private String email;     // 邮箱
    private String company;   // 公司
    // 省略Getter/Setter
}

// SendLog实体
package com.bulk.entity;
public class SendLog {
    private Contact contact;      // 收件人
    private boolean success;      // 是否发送成功
    private int retryCount;       // 重试次数
    // 省略其他字段及Getter/Setter
}

四、运行效果

1.实际接收邮件

屏幕截图 2025-12-23 185058
2.单次邮件发送报告

屏幕截图 2025-12-23 184600
3.发送日志

屏幕截图 2025-12-23 191404

五、学习心得

做这个邮件群发项目让我们特别有感触,让邮件成功发送出去总会遇到各种问题,在编程过程中,加强了排查问题的能力,还有利用AI引入FreeMarker模板引擎,不用硬编码写邮件内容,改改变量就能给不同人发个性化邮件,省了超多事。

六、总结

本项目实现了邮件群发的基本功能,后续考虑添加以下功能并作为课设:

  • 图形化界面,简化操作流程
  • 邮件接收功能
  • 邮件内容在线编辑功能
  • 其他(暂时没想到)
posted @ 2025-12-23 20:21  Writing  阅读(21)  评论(0)    收藏  举报