数据生成PDF定时批量发送到目标邮箱

1.邮箱参数

复制代码
@Configuration
@Data
public class EmailUtils {
    @Value("${email.from}")
    private String from;

    @Value("${email.fromKey}")
    private String fromKey;

    @Value("${email.fromHost}")
    private String fromHost;

    @Value("${email.fromPort}")
    private String fromPort;
}

2.发送邮件

复制代码
  String fromEmail, smtpHost, smtpPort, authCode;
        fromEmail = emailUtils.getFrom();
        authCode = emailUtils.getFromKey();
        smtpHost = emailUtils.getFromHost();
        smtpPort = emailUtils.getFromPort();
        // 生成 PDF
        PDFGenerator pdfGenerator = new PDFGenerator();
        List<String[]> businessData = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime lastSaturdayStart = now.minusDays(7)
                .withHour(0)
                .withMinute(0)
                .withSecond(0);
        // 计算前1天(本周五)的23:59:59
        LocalDateTime thisFridayEnd = now.minusDays(1)
                .withHour(23)
                .withMinute(59)
                .withSecond(59);
        // 输出结果
        String startTime = lastSaturdayStart.format(formatter);
        String endTime = thisFridayEnd.format(formatter);
        // 假设的业务数据
        List<String[]> clientData = new ArrayList<>();
        List<SysDept> deptList = deptMapper.selectSubsidiaryList();
        for (SysDept sysDept : deptList) {
            List<Long> userList = wechatUserMapper.selectSubsidiaryUserId(sysDept.getDeptId());
            if (userList.size() == 0) {
                clientData.add(new String[]{sysDept.getDeptName(), "0", "0", "0", "0"});
                businessData.add(new String[]{sysDept.getDeptName(), "0", "0", "0", "0"});
                continue;
            }
            //客户、实验校
            ClientWeekVO clientWeek = clientMapper.selectWeekInfo(userList, startTime, endTime);
            ClientWeekVO schoolWeek = schoolMapper.selectWeekInfo(userList, startTime, endTime);
            List<Long> clientList = clientMapper.selectClientUser(userList);
            clientData.add(new String[]{sysDept.getDeptName(), clientWeek.getAllCount(), clientWeek.getWeekCount(), schoolWeek.getAllCount(), schoolWeek.getWeekCount()});
            if (clientList.size() == 0) {
                businessData.add(new String[]{sysDept.getDeptName(), "0", "0", "0", "0"});
                continue;
            }
            //回款、订单
            ClientWeekVO returnedWeek = returnedMapper.selectWeekInfo(clientList, startTime, endTime);
            if (!Objects.isNull(returnedWeek)) {
                if (returnedWeek.getWeekCount() == null) {
                    returnedWeek.setWeekCount("0");
                }
                if (returnedWeek.getAllCount() == null) {
                    returnedWeek.setAllCount("0");
                }
            }
            if (Objects.isNull(returnedWeek)) {
                returnedWeek = new ClientWeekVO();
                returnedWeek.setWeekCount("0");
                returnedWeek.setAllCount("0");
            }
            ClientWeekVO orderWeek = ordersMapper.selectWeekInfo(clientList, startTime, endTime);
            if (!Objects.isNull(orderWeek)) {
                if (orderWeek.getWeekCount() == null) {
                    orderWeek.setWeekCount("0");
                }
                if (orderWeek.getAllCount() == null) {
                    orderWeek.setAllCount("0");
                }
            }
            if (Objects.isNull(orderWeek)) {
                orderWeek = new ClientWeekVO();
                orderWeek.setWeekCount("0");
                orderWeek.setAllCount("0");
            }
            businessData.add(new String[]{sysDept.getDeptName(), orderWeek.getAllCount(), orderWeek.getWeekCount(), returnedWeek.getAllCount(), returnedWeek.getWeekCount()});
        }
        String pdfPath = pdfGenerator.generateBusinessReport(businessData, clientData, startTime, endTime);
        String subject = "业务周报";
        // 设置多个收件人
        LambdaQueryWrapper<Email> wrapper = new LambdaQueryWrapper<>();
        List<Email> emailLists = emailMapper.selectList(wrapper);
        List<String> emailList = new ArrayList<>();
        for (Email email : emailLists) {
            emailList.add(email.getEmailAddress());
        }
        // 配置邮件服务器属性
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.host", smtpHost);
        props.put("mail.smtp.port", smtpPort);
        props.put("mail.smtp.ssl.enable", "true");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        // 获取会话对象
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(fromEmail, authCode);
            }
        });
        try {
            // 创建邮件消息
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(fromEmail));
            message.setSubject(subject);
            try {
                InternetAddress[] recipientAddresses = emailList.stream()
                        .map(email -> {
                            try {
                                return new InternetAddress(email);
                            } catch (AddressException e) {
                                System.out.println("无效的邮箱地址: " + email);
                                return null;
                            }
                        })
                        .filter(Objects::nonNull)
                        .toArray(InternetAddress[]::new);
                message.setRecipients(Message.RecipientType.TO, recipientAddresses);
            } catch (Exception e) {
                System.out.println("设置收件人失败: " + e.getMessage());
                return;
            }
            // 创建邮件内容部分
            MimeBodyPart textPart = new MimeBodyPart();
            textPart.setText("请查收附件中的经营周报!");
            // 创建附件部分
            MimeBodyPart attachmentPart = new MimeBodyPart();
            attachmentPart.attachFile(pdfPath);
            // 将文本和附件组合成多重消息
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(textPart);
            multipart.addBodyPart(attachmentPart);
            // 设置邮件内容
            message.setContent(multipart);
            // 发送邮件
            Transport.send(message);
            System.out.println("邮件发送成功,附件已附加!");
        } catch (MessagingException |
                IOException e) {
            e.printStackTrace();
            System.out.println("邮件发送失败!");
        }
    }

3.生成PDF

复制代码
package com.ruoyi.quartz.util.email;

import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.properties.HorizontalAlignment;
import com.itextpdf.layout.properties.TextAlignment;

import java.io.FileOutputStream;
import java.util.List;

/**
 * 业务数据和客户数据 PDF 生成器
 *
 * @author laoyou
 */
public class PDFGenerator {
    public String generateBusinessReport(List<String[]> businessData, List<String[]> clientData, String startTime, String endTime) {
        String pdfPath = "业务周报.pdf";
        try (PdfWriter writer = new PdfWriter(new FileOutputStream(pdfPath));
             PdfDocument pdfDoc = new PdfDocument(writer);
             Document document = new Document(pdfDoc)) {

            // 加载中文字体
            //PdfFont font = PdfFontFactory.createFont("C:\\Windows\\Fonts\\simsun.ttc,1", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
            PdfFont font = PdfFontFactory.createFont("/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc,0", PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
            document.setFont(font);
            // 添加报告标题
            document.add(new Paragraph("业务周报").setFont(font).setBold().setFontSize(18).setTextAlignment(TextAlignment.CENTER));
            // 添加时间区间
            document.add(new Paragraph("数据时间: " + startTime + " 至 " + endTime).setFont(font).setFontSize(12).setTextAlignment(TextAlignment.CENTER));
            // 添加业务情况标题
            document.add(new Paragraph("本周各区业务情况").setFont(font).setBold().setFontSize(16).setTextAlignment(TextAlignment.CENTER));
            // 业务数据表格
            document.add(new Paragraph("业务数据").setFont(font).setBold().setFontSize(14).setTextAlignment(TextAlignment.CENTER));
            Table businessTable = new Table(new float[]{2, 2, 2, 2, 2});
            businessTable.setHorizontalAlignment(HorizontalAlignment.CENTER);
            String[] businessHeaders = {
                    "子公司/大区",
                    "订单 总金额",
                    "订单 上周增加额",
                    "回款 总金额",
                    "回款 上周增加额"
            };
            for (String header : businessHeaders) {
                businessTable.addCell(new Cell().add(new Paragraph(header).setFont(font).setBold().setTextAlignment(TextAlignment.CENTER)));
            }
            for (String[] row : businessData) {
                for (String cellData : row) {
                    businessTable.addCell(new Cell().add(new Paragraph(cellData).setFont(font).setTextAlignment(TextAlignment.CENTER)));
                }
            }
            document.add(businessTable);
            // 客户数据表格
            document.add(new Paragraph("客户数据").setFont(font).setBold().setFontSize(14).setTextAlignment(TextAlignment.CENTER));
            Table clientTable = new Table(new float[]{2, 2, 2, 2, 2});
            clientTable.setHorizontalAlignment(HorizontalAlignment.CENTER);
            String[] clientHeaders = {
                    "子公司/大区",
                    "客户 总数量",
                    "客户 上周增加数",
                    "实验校 总数量",
                    "实验校 上周增加数"
            };
            for (String header : clientHeaders) {
                clientTable.addCell(new Cell().add(new Paragraph(header).setFont(font).setBold().setTextAlignment(TextAlignment.CENTER)));
            }
            for (String[] row : clientData) {
                for (String cellData : row) {
                    clientTable.addCell(new Cell().add(new Paragraph(cellData).setFont(font).setTextAlignment(TextAlignment.CENTER)));
                }
            }
            document.add(clientTable);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("PDF 生成失败!");
        }
        return pdfPath;
    }
}

4.示例

相关推荐
RainbowSea12 小时前
11. LangChain4j + Tools(Function Calling)的使用详细说明
java·langchain·ai编程
考虑考虑16 小时前
Jpa使用union all
java·spring boot·后端
用户37215742613516 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊18 小时前
Java学习第22天 - 云原生与容器化
java
渣哥19 小时前
原来 Java 里线程安全集合有这么多种
java
间彧19 小时前
Spring Boot集成Spring Security完整指南
java
间彧20 小时前
Spring Secutiy基本原理及工作流程
java
Java水解21 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆1 天前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学1 天前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端