数据生成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.示例

相关推荐
芦屋花绘4 分钟前
Java的JUC详细全解
java·开发语言·jvm·spring boot·kafka
珠峰下的沙砾12 分钟前
如何将IDP映射属性添加,到accountToken中 方便项目获取登录人信息
java
lfwh19 分钟前
Java 实现单链表翻转(附详细注释)
java·开发语言·python
元亓亓亓1 小时前
java后端开发day35--集合进阶(四)--双列集合:Map&HashMap&TreeMap
java·开发语言
独立开阀者_FwtCoder2 小时前
狂收 33k+ star!全网精选的 MCP 一网打尽!!
java·前端·javascript
再路上12162 小时前
direct_visual_lidar_calibration iridescence库问题
java·服务器·数据库
兔子蟹子2 小时前
Java 实现SpringContextUtils工具类,手动获取Bean
java·开发语言
jackson凌3 小时前
【Java学习方法】终止循环的关键字
java·笔记·学习方法
种时光的人3 小时前
Java多线程的暗号密码:5分钟掌握wait/notify
java·开发语言
我家领养了个白胖胖3 小时前
#和$符号使用场景 注意事项
java·后端·mybatis