Java导出通过Word模板导出docx文件并通过QQ邮箱发送

news2025/1/27 0:06:13

一、创建Word模板

{{company}}{{Date}}服务器运行情况报告

一、服务器:总告警次数:{{ServerTotal}}
服务器IP:{{IPA}},总共告警次数:{{ServerATotal}} 
服务器IP:{{IPB}},总共告警次数:{{ServerBTotal}} 
服务器IP:{{IPC}},总共告警次数:{{ServerCTotal}} 

二、应用程序:总告警次数{{ApplicationTotal}} 
服务器IP:{{IPA}},包含{{ApplicationAName}}应用程序服务,总共告警次数:{{ApplicationATotal}}
服务器IP:{{IPB}},包含{{ApplicationBName}}应用程序服务,总共告警次数:{{ApplicationBTotal}}
服务器IP:{{IPC}},包含{{ApplicationCName}}应用程序服务,总共告警次数:{{ApplicationCTotal}}

三、数据库:总告警次数{{DBTotal}} 
服务器IP:{{IPA}},包含{{DBAName}}数据库,总共告警次数:{{DBATotal}}
服务器IP:{{IPB}},包含{{DBBName}}数据库,总共告警次数:{{DBBTotal}}
服务器IP:{{IPC}},包含{{DBCName}}数据库,总共告警次数:{{DBCTotal}}

四、中间件:总告警次数{{MiddleWareTotal}} 
服务器IP:{{IPA}},包含{{MiddleWareAName}}中间件,总共告警次数:{{MiddleWareATotal}}
服务器IP:{{IPB}},包含{{MiddleWareBName}}中间件,总共告警次数:{{MiddleWareBTotal}}
服务器IP:{{IPC}},包含{{MiddleWareCName}}中间件,总共告警次数:{{MiddleWareCTotal}} 

五、接口:总告警次数{{InterfaceTotal}} 
服务器IP:{{IPA}},包含{{InterfaceAName}}接口服务,总共告警次数:{{InterfaceATotal}}
服务器IP:{{IPB}},包含{{InterfaceBName}}接口服务,总共告警次数:{{InterfaceBTotal}}
服务器IP:{{IPC}},包含{{InterfaceCName}}接口服务,总共告警次数:{{InterfaceCTotal}}

将上述内容存入一个docx文件中,放到resources文件夹下
在这里插入图片描述

二、编写代码

package com.gitee.pifeng.monitoring.server.business.server.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gitee.pifeng.monitoring.server.business.server.dao.*;
import com.gitee.pifeng.monitoring.server.business.server.entity.*;
import com.gitee.pifeng.monitoring.server.business.server.service.IAlarmService;
import com.gitee.pifeng.monitoring.server.config.WordTemplateConfig;

import com.gitee.pifeng.monitoring.server.util.db.SelectEmailsService;
import org.apache.poi.util.StringUtil;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.util.StringUtils;


import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * description 导出word版本的报表
 *
 * @author yhj
 * @date 2025-01-06 17:08:15
 */

@RequestMapping("/ExportWord")
@RestController
public class ExportWordReportController {
    @Autowired
    private WordTemplateConfig wordTemplateConfig;



    /**
     * 告警服务接口
     */
    @Autowired
    private IAlarmService alarmService;

    @Autowired
    private IMonitorInstanceDao monitorInstanceDao;

    @Autowired
    private IMonitorAlarmRecordDao monitorAlarmRecordDao;

    @Autowired
    private IMonitorDbDao monitorDbDao;

    @Autowired
    private IMonitorTcpDao monitorTcpDao;

    @Autowired
    private IMonitorHttpDao monitorHttpDao;

    @Autowired
    private SelectEmailsService emailsService;


    public void exportWordTemplate(HttpServletResponse response, Map<String, String> data, String filename) {
        String companyName = emailsService.selectCompanyName();
        data.put("company", companyName);

        try {
            String filePath = URLDecoder.decode(getClass().getClassLoader().getResource("templates/static/WordReportTemplete.docx").getPath(), "UTF-8");
            // 读取Word模板
            FileInputStream fis = new FileInputStream(filePath);
            XWPFDocument document = new XWPFDocument(fis);
            // 将填充后的文档写入响应输出流
            wordTemplateConfig.replaceTextInDocument(document, data);
            // 设置响应头,指定下载文件类型和名称
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + filename + ".docx");
            document.write(response.getOutputStream());
            // 关闭资源
            document.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private void exportEmptyWordTemplate(HttpServletResponse response, Map<String, String> data) {
        String companyName = emailsService.selectCompanyName();

        String filename = URLEncoder.encode(String.valueOf(new StringBuilder(companyName).append("现场暂无数据"))).replaceAll("\\+", "%20");
        data.put("company", companyName);
        try {
            String filePath = URLDecoder.decode(getClass().getClassLoader().getResource("templates/static/EmptyWordReportTemplete.docx").getPath(), "UTF-8");

            // 读取Word模板
            FileInputStream fis = new FileInputStream(filePath);
            XWPFDocument document = new XWPFDocument(fis);
            // 将填充后的文档写入响应输出流
            wordTemplateConfig.replaceTextInDocument(document, data);
            // 设置响应头,指定下载文件类型和名称
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + filename + ".docx");
            document.write(response.getOutputStream());
            // 关闭资源
            document.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    /**
     * 本日服务器报错信息word导出
     *
     * @param response
     */
    @GetMapping("/getThisDayWordReport")
    public void getDayWordReport(HttpServletResponse response) {
        String companyName = emailsService.selectCompanyName();
        Map<String, String> data = new HashMap<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        String TodayDay = simpleDateFormat.format(date);
        data.put("Date", TodayDay);
        Integer flag = 0;  // 0代表今日
        //文件名,以下方法用于防止中文编码错误
        String name = String.valueOf(new StringBuilder(companyName).append(TodayDay).append("服务器报错信息"));
        String filename = URLEncoder.encode(name).replaceAll("\\+", "%20");
        thisWordInfo(response, flag, TodayDay, data, filename);
    }
    // 将导出的信息填充给word
    private void thisWordInfo(HttpServletResponse response, Integer flag, String Date, Map<String, String> data, String filename) {

        // 查询所有IP
        List<String> IpList = getIpList();
        if (IpList.size() == 0) {
            exportEmptyWordTemplate(response, data);
        } else {
            List<ExportWordReport> listA = new ArrayList<>();
            if (!IpList.get(0).isEmpty()) {
                String IPA = IpList.get(0);
                if (flag == 0) {
                    // 当日报错个数
                    listA = alarmService.selectWordDayAlarmTotal(IPA, Date);
                } else if (flag == 1) {
                    // 本周报错个数
                    listA = alarmService.selectWordWeekAlarmTotal(IPA, Date);
                } else if (flag == 2) {
                    // 本月报错个数
                    listA = alarmService.selectWordMonthAlarmTotal(IPA, Date);
                } else if (flag == 3) {
                    // 本年报错个数
                    listA = alarmService.selectWordYearAlarmTotal(IPA, Date);
                }
                // 汇总各项报错个数
                Map<String, Integer> mapA = listA.stream().collect(Collectors.toMap(ExportWordReport::getName, ExportWordReport::getTotal));
                // 查询该IP下所有应用程序的名称
                String applicationName = getApplicationNameList(IPA);
                // 查询该IP下所有数据库名字
                String DBName = getDBNameList(IPA);
                // 查询该IP下所有中间件名字
                String MiddleWareName = getMiddleNameList(IPA);
                // 查询该IP下所有接口名称
                String InterfaceName = getInterfaceNameList(IPA);
                // 填充word里面的字段
                data.put("IPA", IPA);
                data.put("ApplicationAName", !applicationName.isEmpty() ? applicationName : "0个");
                data.put("DBAName", !DBName.isEmpty() ? DBName : "0个");
                data.put("MiddleWareAName", !MiddleWareName.isEmpty() ? MiddleWareName : "0个");
                data.put("InterfaceAName", !InterfaceName.isEmpty() ? InterfaceName : "0个");
                // 服务器
                data.put("ServerATotal", mapA.get("SERVER") != null ? String.valueOf(mapA.get("SERVER")) : "0");
                // 应用
                data.put("ApplicationATotal", mapA.get("INSTANCE") != null ? String.valueOf(mapA.get("INSTANCE")) : "0");
                // 数据库
                data.put("DBATotal", mapA.get("DATABASE") != null ? String.valueOf(mapA.get("DATABASE")) : "0");
                // 中间件
                data.put("MiddleWareATotal", mapA.get("TCP4SERVICE") != null ? String.valueOf(mapA.get("TCP4SERVICE")) : "0");
                // 接口
                data.put("InterfaceATotal", mapA.get("HTTP4SERVICE") != null ? String.valueOf(mapA.get("HTTP4SERVICE")) : "0");
            }
            if (!IpList.get(1).isEmpty()) {
                List<ExportWordReport> listB = new ArrayList<>();
                String IPB = IpList.get(1);
                if (flag == 0) {
                    listB = alarmService.selectWordDayAlarmTotal(IPB, Date);

                } else if (flag == 1) {
                    // 本周报错信息
                    listB = alarmService.selectWordWeekAlarmTotal(IPB, Date);
                } else if (flag == 2) {
                    // 本月报错个数
                    listB = alarmService.selectWordMonthAlarmTotal(IPB, Date);
                } else if (flag == 3) {
                    // 本年报错个数
                    listB = alarmService.selectWordYearAlarmTotal(IPB, Date);
                }
                // 汇总各项报错个数
                Map<String, Integer> mapB = listB.stream().collect(Collectors.toMap(ExportWordReport::getName, ExportWordReport::getTotal));
                // 查询该IP下所有应用程序的名称
                String applicationName = getApplicationNameList(IPB);
                // 查询该IP下所有数据库名字
                String DBName = getDBNameList(IPB);
                // 查询该IP下所有中间件名字
                String MiddleWareName = getMiddleNameList(IPB);
                // 查询该IP下所有接口名称
                String InterfaceName = getInterfaceNameList(IPB);
                data.put("IPB", IPB);
                data.put("ApplicationBName", !applicationName.isEmpty() ? applicationName : "0个");
                data.put("DBBName", !DBName.isEmpty() ? DBName : "0个");
                data.put("MiddleWareBName", !MiddleWareName.isEmpty() ? MiddleWareName : "0个");
                data.put("InterfaceBName", !InterfaceName.isEmpty() ? InterfaceName : "0个");
                // 服务器
                data.put("ServerBTotal", mapB.get("SERVER") != null ? String.valueOf(mapB.get("SERVER")) : "0");
                // 应用
                data.put("ApplicationBTotal", mapB.get("INSTANCE") != null ? String.valueOf(mapB.get("INSTANCE")) : "0");
                // 数据库
                data.put("DBBTotal", mapB.get("DATABASE") != null ? String.valueOf(mapB.get("DATABASE")) : "0");
                // 中间件
                data.put("MiddleWareBTotal", mapB.get("TCP4SERVICE") != null ? String.valueOf(mapB.get("TCP4SERVICE")) : "0");
                // 接口
                data.put("InterfaceBTotal", mapB.get("HTTP4SERVICE") != null ? String.valueOf(mapB.get("HTTP4SERVICE")) : "0");
            }
            if (!IpList.get(2).isEmpty()) {
                List<ExportWordReport> listC = new ArrayList<>();
                String IPC = IpList.get(2);
                if (flag == 0) {
                    listC = alarmService.selectWordDayAlarmTotal(IPC, Date);
                } else if (flag == 1) {
                    // 本周报错个数
                    listC = alarmService.selectWordWeekAlarmTotal(IPC, Date);
                } else if (flag == 2) {
                    // 本月报错个数
                    listC = alarmService.selectWordMonthAlarmTotal(IPC, Date);
                } else if (flag == 3) {
                    // 本年报错个数
                    listC = alarmService.selectWordYearAlarmTotal(IPC, Date);
                }
                // 汇总各项报错个数
                Map<String, Integer> mapC = listC.stream().collect(Collectors.toMap(ExportWordReport::getName, ExportWordReport::getTotal));
                // 查询该IP下所有应用程序的名称
                String applicationName = getApplicationNameList(IPC);
                // 查询该IP下所有数据库名字
                String DBName = getDBNameList(IPC);
                // 查询该IP下所有中间件名字
                String MiddleWareName = getMiddleNameList(IPC);
                // 查询该IP下所有接口名称
                String InterfaceName = getInterfaceNameList(IPC);
                data.put("IPC", IPC);
                data.put("ApplicationCName", !applicationName.isEmpty() ? applicationName : "0个");
                data.put("DBCName", DBName);
                data.put("MiddleWareCName", !MiddleWareName.isEmpty() ? MiddleWareName : "0个");
                data.put("InterfaceCName", !InterfaceName.isEmpty() ? InterfaceName : "0个");
                // 服务器
                data.put("ServerCTotal", mapC.get("SERVER") != null ? String.valueOf(mapC.get("SERVER")) : "0");
                // 应用
                data.put("ApplicationCTotal", mapC.get("INSTANCE") != null ? String.valueOf(mapC.get("INSTANCE")) : "0");
                // 数据库
                data.put("DBCTotal", mapC.get("DATABASE") != null ? String.valueOf(mapC.get("DATABASE")) : "0");
                // 中间件
                data.put("MiddleWareCTotal", mapC.get("TCP4SERVICE") != null ? String.valueOf(mapC.get("TCP4SERVICE")) : "0");
                // 接口
                data.put("InterfaceCTotal", mapC.get("HTTP4SERVICE") != null ? String.valueOf(mapC.get("HTTP4SERVICE")) : "0");
            }
            // 所有服务器报错信息条数总和
            int ServerTotal = Integer.parseInt(data.get("ServerATotal")) + Integer.parseInt(data.get("ServerBTotal")) + Integer.parseInt(data.get("ServerCTotal"));
            data.put("ServerTotal", String.valueOf(ServerTotal));
            // 所有应用程序报错信息总和
            int ApplicationTotal = Integer.parseInt(data.get("ApplicationATotal")) + Integer.parseInt(data.get("ApplicationBTotal")) + Integer.parseInt(data.get("ApplicationCTotal"));
            data.put("ApplicationTotal", String.valueOf(ApplicationTotal));
            //所有数据库报错信息总和
            int DBTotal = Integer.parseInt(data.get("DBATotal")) + Integer.parseInt(data.get("DBBTotal")) + Integer.parseInt(data.get("DBCTotal"));
            data.put("DBTotal", String.valueOf(DBTotal));
            //所有中间件报错信息总和
            int MiddleWareTotal = Integer.parseInt(data.get("MiddleWareATotal")) + Integer.parseInt(data.get("MiddleWareBTotal")) + Integer.parseInt(data.get("MiddleWareCTotal"));
            data.put("MiddleWareTotal", String.valueOf(MiddleWareTotal));
            //所有接口报错信息总和
            int InterfaceTotal = Integer.parseInt(data.get("InterfaceATotal")) + Integer.parseInt(data.get("InterfaceBTotal")) + Integer.parseInt(data.get("InterfaceCTotal"));
            data.put("InterfaceTotal", String.valueOf(InterfaceTotal));
            exportWordTemplate(response, data, filename);
        }

    }

    // 查询所有接口名称
    private String getInterfaceNameList(String IP) {
        LambdaQueryWrapper<MonitorHttp> queryInterfaceNameWrapper = new LambdaQueryWrapper<>();
        queryInterfaceNameWrapper.select(MonitorHttp::getDescr)
                .ne(MonitorHttp::getDescr,null)
                .ne(MonitorHttp::getDescr,"")
                .eq(MonitorHttp::getHostnameSource, IP)
                .groupBy(MonitorHttp::getDescr);
        List<String> InterfaceList = monitorHttpDao.selectList(queryInterfaceNameWrapper)
                .stream()
                .filter(item -> item!=null)
                .map(MonitorHttp::getDescr)
                .collect(Collectors.toList());
        String InterfaceName = InterfaceList.stream().map(String::toString).collect(Collectors.joining("、"));
        return InterfaceName;
    }

    // 查询所有IP
    private List<String> getIpList() {
        LambdaQueryWrapper<MonitorAlarmRecord> queryIPWrapper = new LambdaQueryWrapper<>();
        queryIPWrapper.select(MonitorAlarmRecord::getIp).groupBy(MonitorAlarmRecord::getIp);
        List<String> IpList = monitorAlarmRecordDao.selectList(queryIPWrapper)
                .stream()
                .filter(item -> item != null)
                .map(MonitorAlarmRecord::getIp)
                .collect(Collectors.toList());
        return IpList;
    }

    // 查询该IP下所有中间件的名称
    private String getMiddleNameList(String IP) {
        LambdaQueryWrapper<MonitorTcp> queryMiddleNameWrapper = new LambdaQueryWrapper<>();
        queryMiddleNameWrapper.select(MonitorTcp::getDescr)
                .ne(MonitorTcp::getDescr,"")
                .ne(MonitorTcp::getDescr,null)
                .eq(MonitorTcp::getHostnameSource, IP)
                .groupBy(MonitorTcp::getDescr);
        List<String> MiddleWareList = monitorTcpDao.selectList(queryMiddleNameWrapper)
                .stream()
                .filter(item -> item != null)
                .map(MonitorTcp::getDescr)
                .collect(Collectors.toList());
        String MiddleWareName = MiddleWareList.stream().map(String::toString).collect(Collectors.joining("、"));
        return MiddleWareName;
    }

    // 查询该IP下所有应用程序的名称
    private String getApplicationNameList(String IP) {
        // 查询该IP下所有应用程序的名称
        LambdaQueryWrapper<MonitorInstance> queryInstanceNameWrapper = new LambdaQueryWrapper<>();
        queryInstanceNameWrapper.select(MonitorInstance::getInstanceName) // 指定查询字段
                .ne(MonitorInstance::getInstanceName,"")
                .ne(MonitorInstance::getInstanceName,null)
                .eq(MonitorInstance::getIp, IP)          // 添加 IP 条件
                .groupBy(MonitorInstance::getInstanceName); // 去重(相当于 DISTINCT)
        List<String> ApplicationNameList = monitorInstanceDao.selectList(queryInstanceNameWrapper)
                .stream()
                .map(MonitorInstance::getInstanceName) // 提取字段值
                .distinct().collect(Collectors.toList());// 确保去重
        String applicationName = ApplicationNameList.stream().map(String::toString).collect(Collectors.joining("、"));
        return applicationName;
    }

    // 查询所有数据库名字公共方法
    private String getDBNameList(String IP) {
        LambdaQueryWrapper<MonitorDb> queryDBListWrapper = new LambdaQueryWrapper<>();
        queryDBListWrapper.select(MonitorDb::getDbType)
                .ne(MonitorDb::getDbType,"")
                .ne(MonitorDb::getDbType,null)
                .eq(MonitorDb::getIp, IP)
                .groupBy(MonitorDb::getDbType);
        List<String> DBList = monitorDbDao.selectList(queryDBListWrapper).stream().filter(item -> item != null).map(MonitorDb::getDbType).collect(Collectors.toList());
        String DBName = DBList.stream().map(String::toString).collect(Collectors.joining("、"));
        return DBName;
    }


}

工具类,主要读取信息并写入word模板内

package com.gitee.pifeng.monitoring.server.config;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public class WordTemplateConfig {

        public void replaceTextInDocument(XWPFDocument document, Map<String, String> data) {
            // 替换段落中的占位符
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                StringBuilder paragraphText = new StringBuilder();
                List<XWPFRun> runs = paragraph.getRuns();
                if (runs != null) {
                    // 收集段落中的所有文本
                    for (XWPFRun run : runs) {
                        paragraphText.append(run.getText(0) != null ? run.getText(0) : "");
                    }
                    // 替换占位符
                    String replacedText = paragraphText.toString();
                    for (Map.Entry<String, String> entry : data.entrySet()) {
                        replacedText = replacedText.replace("{{" + entry.getKey() + "}}", entry.getValue() != null ? entry.getValue() : "");
                    }
                    // 清空原有 runs
                    for (int i = runs.size() - 1; i >= 0; i--) {
                        paragraph.removeRun(i);
                    }
                    // 重新设置替换后的文本
                    XWPFRun newRun = paragraph.createRun();
                    newRun.setText(replacedText);
                }
            }

            // 替换表格中的占位符
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        for (XWPFRun run : paragraph.getRuns()) {
                            String text = run.getText(0);
                            if (text != null) {
                                for (Map.Entry<String, String> entry : data.entrySet()) {
                                    if (text.contains("{{" + entry.getKey() + "}}")) {
                                        text = text.replace("{{" + entry.getKey() + "}}", entry.getValue());
                                        run.setText(text, 0);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}









三、发送邮箱

@RequestMapping("/SendWord")
@RestController
public class SendWordReportController {


    @Autowired
    private EmailSender emailSender;

    @Autowired
    private SelectEmailsService emailsService;

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    String date = simpleDateFormat.format(new Date());


    /**
     * 发送日报表
     */
    @PostMapping("/sendDayWordReport")
    public void sendDayWordReport()  {
        List<String> emails = emailsService.findEmail();
         String companyName = emailsService.selectCompanyName();
        String name = companyName+new StringBuilder(date).append("日服务器报错信息汇总");
        try {
            // 调用接口下载 Excel 文件
            String apiUrl = "http://localhost:16000/phoenix-server/ExportWord/getThisDayWordReport";
            File wordFile = FileDownloader.downloadWordFile(apiUrl);
            // 接收邮件的邮箱
            for (String email: emails) {
                emailSender.sendEmailWithAttachment(email,wordFile,name);
            }
//            emailSender.sendEmailWithAttachment(toEmail,wordFile,name);
        } catch (IOException | MessagingException e) {
            e.printStackTrace();
        }
    }
   }
  }
package com.gitee.pifeng.monitoring.server.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.io.IOException;
import java.util.Properties;

/**
 * description 发送报表数据
 *
 * @author yhj
 * @date 2025-01-02 15:39:08
 */



@Component
public class EmailSender {
    
    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;


    @Autowired
    private JavaMailSender sender;

    public void sendEmailWithAttachment(String toEmail,File attachmentFile,String name) throws MessagingException, IOException {
        // 设置邮件属性
        Properties properties = new Properties();
        properties.put("mail.smtp.host","smtp.exmail.qq.com");
        properties.put("mail.smtp.port",465);
        properties.put("mail.smtp.auth","true");
        properties.put("mail.smtp.starttls.enable","true");

        // 获取邮件会话
//        Session session = Session.getInstance(properties, new Authenticator() {
//            @Override
//            protected PasswordAuthentication getPasswordAuthentication() {
//                // 填写发送者邮箱和授权码
//                return new PasswordAuthentication(username, password);
//            }
//        });
        //创建邮件内容
        // 创建MimeMessage对象
        MimeMessage message = sender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true); // true表示支持附件

        helper.setFrom("249@qq.com");
        helper.setTo(toEmail);
//        String subject = String.valueOf(new StringBuilder(companyName).append("服务器运行状况报表"));
        message.setSubject(name);
        // 创建一个Multipart对象,包含邮件正文和附件
        Multipart multipart = new MimeMultipart();
        // 邮件正文部分
//        MimeBodyPart messageBodyPart = new MimeBodyPart();
//        messageBodyPart.setText(name);
//        multipart.addBodyPart(messageBodyPart);

        // 邮件附件部分
        MimeBodyPart attachmentPart = new MimeBodyPart();
        attachmentPart.attachFile(attachmentFile);
        attachmentPart.setFileName(name+".docx");
        multipart.addBodyPart(attachmentPart);// 附加附件文件
        message.setContent(multipart);

        // 发送邮件
        sender.send(message);
        System.out.println("邮件发送成功!");


    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2283676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统编程:进程状态和进程优先级/nice

目录 一,相对于OS的进程状态 1.1运行状态 1.2阻塞状态 1.3挂起状态 二,并发执行与进程切换 2.1,CPU并发执行 2.2进程切换 三,Linux内核管理进程状态的方法 3.1查看进程状态 3.2R状态 3.3S状态 3.4D状态 3.5T状态 3.6X状态 3.7Z状态 3.8孤儿进程 四,进程优先级 …

0 基础学运维:解锁 K8s 云计算运维工程师成长密码

前言&#xff1a;作为一个过来人&#xff0c;我曾站在技术的门槛之外&#xff0c;连电脑运行内存和内存空间都傻傻分不清&#xff0c;完完全全的零基础。但如今&#xff0c;我已成长为一名资深的k8s云计算运维工程师。回顾这段历程&#xff0c;我深知踏上这条技术之路的艰辛与不…

在 vscode + cmake + GNU 工具链的基础上配置 JLINK

安装 JLINK JLINK 官网链接 下载安装后找到安装路径下的可执行文件 将此路径添加到环境变量的 Path 中。 创建 JFlash 项目 打开 JFlash&#xff0c;选择新建项目 选择单片机型号 在弹出的窗口中搜索单片机 其他参数根据实际情况填写 新建完成&#xff1a; 接下来设置…

【全栈】SprintBoot+vue3迷你商城(9)

【全栈】SprintBootvue3迷你商城&#xff08;9&#xff09; 往期的文章都在这里啦&#xff0c;大家有兴趣可以看一下 后端部分&#xff1a; 【全栈】SprintBootvue3迷你商城&#xff08;1&#xff09; 【全栈】SprintBootvue3迷你商城&#xff08;2&#xff09; 【全栈】Spr…

省市区三级联动

引言 在网页中&#xff0c;经常会遇到需要用户选择地区的场景&#xff0c;如注册表单、地址填写等。为了提供更好的用户体验&#xff0c;我们可以实现一个三级联动的地区选择器&#xff0c;让用户依次选择省份、城市和地区。 效果展示&#xff1a; 只有先选择省份后才可以选择…

Fullcalendar @fullcalendar/react 样式错乱丢失问题和导致页面卡顿崩溃问题

问题描述&#xff1a; 我使用 fullcalendar的react版本时&#xff0c;出现了一个诡异的问题&#xff0c;当我切换到 一个iframe页面时&#xff08;整个页面是一个iframe嵌入的&#xff09;&#xff0c;再切换回来日历的样式丢失了&#xff01;不仅丢失了样式还导致页面崩溃了&…

dm8在Linux环境安装精简步骤说明(2024年12月更新版dm8)

dm8在Linux环境安装详细步骤 - - 2025年1月之后dm8 环境介绍1 修改操作系统资源限制2 操作系统创建用户3 操作系统配置4 数据库安装5 初始化数据库6 实例参数优化7 登录数据库配置归档与备份8 配置审计9 创建用户10 屏蔽关键字与数据库兼容模式11 jdbc连接串配置12 更多达梦数据…

S4 HANA更改Tax base Amount的字段控制

本文主要介绍在S4 HANA OP中Tax base Amount的字段控制相关设置。具体请参照如下内容&#xff1a; 1. 更改Tax base Amount的字段控制 以上配置用于控制FB60/FB65/FB70/FB75/MIRO的页签“Tax”界面是否可以修改“Tax base Amount”&#xff0c; 如果勾选Change 表示可以修改T…

JVM堆空间

一、堆空间的核心概述 一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。Java堆区在JVM启动的时候即被创建&#xff0c;其空间大小也就确定了。是JVM管理的最大一块内存空间。 堆内存的大小是可以调节的。堆可以处于物理上不连续的内存空间中&#xff…

《深入解析:DOS检测的技术原理与方法》

DDOS入侵检测与防御 一、实现Linux下DDOS的入侵检测与防御 利用Python编程实现对wrk的泛洪攻击检测&#xff0c;并让程序触发调用Linux命令实现防御: 1、泛洪攻击的检测&#xff0c;可以考虑使用的命令&#xff0c;这些命令可以通过Python进行调用和分析 (1) netstat -ant …

PID如何调试,如何配置P,I,D值,如何适配pwm的定时器配置,如何给小车配电源

首先你要搞清楚PID公式原理 PID算法解析PID算法解析_pid滤波算法-CSDN博客 然后你要明白调试原理 首先要确定一个电源 电源决定了你后面调试时电机转动速度大小和pwm占空比的关系&#xff0c;电源电压越大那要转到同一速度所需的占空比越小&#xff0c;反之电源电压越小那要…

小马模拟器-第三方全街机游戏模拟器

链接&#xff1a;https://pan.xunlei.com/s/VOHSiB6st-f3RWlIK01MS2fUA1?pwd44v7# 1.小马模拟器是一款完全免费的游戏模拟器软件&#xff0c;支持街机&#xff08;FBA,MAME,PGM2&#xff09;,3DS,WII,NGC,DC,SS,DOS,MD,WSC,NDS,JAVA,PCE,FC,SFC,GBA,GBC,PSP,PS,N64等多种游戏…

微信小程序date picker的一些说明

微信小程序的picker是一个功能强大的组件&#xff0c;它可以是一个普通选择器&#xff0c;也可以是多项选择器&#xff0c;也可以是时间、日期、省市区选择器。 官方文档在这里 这里讲一下date picker的用法。 <view class"section"><view class"se…

【算法】递归型枚举与回溯剪枝初识

递归型枚举与回溯剪枝初识 1.枚举子集2.组合型枚举3.枚举排列4.全排列问题 什么是搜索&#xff1f;搜索&#xff0c;是一种枚举&#xff0c;通过穷举所有的情况来找到最优解&#xff0c;或者统计合法解的个数。因此&#xff0c;搜索有时候也叫作暴搜。搜索一般分为深度优先搜索…

rocketmq-product-send方法源码分析

先看有哪些send方法 首先说红圈的 有3个红圈。归类成3种发送方式。假设前提条件&#xff0c;发送的topic&#xff0c;有3个broker&#xff0c;每个broker总共4个write队列&#xff0c;总共有12个队列。 普通发送。负载均衡12个队列。指定超时时间指定MessageQueue,发送&#…

69.在 Vue 3 中使用 OpenLayers 拖拽实现放大区域的效果(DragPan)

引言 在现代 Web 开发中&#xff0c;地图功能已经成为许多应用的重要组成部分。OpenLayers 是一个功能强大的开源地图库&#xff0c;支持多种地图源和交互操作。Vue 3 是一个流行的前端框架&#xff0c;以其响应式数据和组件化开发著称。本文将介绍如何在 Vue 3 中集成 OpenLa…

77,【1】.[CISCN2019 华东南赛区]Web4

有句英文&#xff0c;看看什么意思 好像也可以不看 进入靶场 点击蓝色字体 我勒个豆&#xff0c;百度哇 所以重点应该在url上&#xff0c;属于任意文件读取类型 接下来该判断框架了 常见的web框架如下 一&#xff0c;Python 框架 1.Flask URL 示例 1&#xff1a;http://…

手撕B-树

一、概述 1.历史 B树&#xff08;B-Tree&#xff09;结构是一种高效存储和查询数据的方法&#xff0c;它的历史可以追溯到1970年代早期。B树的发明人Rudolf Bayer和Edward M. McCreight分别发表了一篇论文介绍了B树。这篇论文是1972年发表于《ACM Transactions on Database S…

一文简单回顾复习Java基础概念

还是和往常一样&#xff0c;我以提问的方式回顾复习&#xff0c;今天回顾下Java小白入门应该知道的一些基础知识 Java语言有哪些特点呢&#xff1f; Java语言的特点有&#xff1a; 面向对象&#xff0c;主要是封装、继承、多态&#xff1b;平台无关性&#xff0c;“一次编写…

GCC之编译(8)AR打包命令

GCC之(8)AR二进制打包命令 Author: Once Day Date: 2025年1月23日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章请查看专栏: Linux实践记录_Once-Day的博客-C…