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

一、创建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("邮件发送成功!");


    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能化加速标准和协议的更新并推动验证IP(VIP)在芯片设计中的更广泛应用

作者&#xff1a;Karthik Gopal, SmartDV Technologies亚洲区总经理 智权半导体科技&#xff08;厦门&#xff09;有限公司总经理 随着AI技术向边缘和端侧设备广泛渗透&#xff0c;芯片设计师不仅需要考虑在其设计中引入加速器&#xff0c;也在考虑采用速度更快和带宽更高的总…

RabbitMQ5-死信队列

目录 死信的概念 死信的来源 死信实战 死信之TTl 死信之最大长度 死信之消息被拒 死信的概念 死信&#xff0c;顾名思义就是无法被消费的消息&#xff0c;一般来说&#xff0c;producer 将消息投递到 broker 或直接到queue 里了&#xff0c;consumer 从 queue 取出消息进…

git常用命令学习

目录 文章目录 目录第一章 git简介1.Git 与SVN2.Git 工作区、暂存区和版本库 第二章 git常用命令学习1.ssh设置2.设置用户信息3.常用命令设置1.初始化本地仓库init2.克隆clone3.查看状态 git status4.添加add命令5.添加评论6.分支操作1.创建分支2.查看分支3.切换分支4.删除分支…

私有包上传maven私有仓库nexus-2.9.2

一、上传 二、获取相应文件 三、最后修改自己的pom文件

汽车定速巡航

配备定速巡航功能的车型&#xff0c;一般在方向盘附近设有4~6个按键&#xff08;可能共用键位&#xff09;。 要设置定速巡航&#xff0c;不仅需要方向盘上的按键&#xff0c;还要油门配合。 设置的一般流程&#xff1a; 开关&#xff1a;类似步枪上的“保险”&#xff0c;按…

安宝特方案 | AR在供应链管理中的应用:提升效率与透明度

随着全球化的不断深入和市场需求的快速变化&#xff0c;企业对供应链管理的要求也日益提高。如何在复杂的供应链环境中提升效率、降低成本&#xff0c;并确保信息的透明度&#xff0c;成为了各大行业亟待解决的问题。而增强现实&#xff08;AR&#xff09;技术&#xff0c;特别…

JavaScript(8)-函数

一.什么是函数&#xff1a;执行特定任务的代码块 讲js中需要的公共部分抽取并封装&#xff0c;谁用谁调用&#xff0c;代码复用。 先声明&#xff0c;后调用 使用function函数名需要调用的内容 使用&#xff1a;函数名&#xff08;&#xff09; 二.使用方式 声明&a…

HTML<label>标签

例子 三个带标签的单选按钮&#xff1a; <form action"/action_page.php"> <input type"radio" id"html" name"fav_language" value"HTML"> <label for"html">HTML</label><br&…

4.flask-SQLAlchemy,表Model定义、增删查改操作

介绍 SQLAlchemy是对数据库的一个抽象 开发者不用直接与SQL语句打交道 Python对象来操作数据库 SQLAlchemy是一个关系型数据库 安装 flask中SQLAlchemy的配置 from flask import Flask from demo.user_oper import userdef create_app():app Flask(__name__)# 使用sessi…

【C++初阶】第11课—vector

文章目录 1. 认识vector2. vector的遍历3. vector的构造4. vector常用的接口5. vector的容量6. vector的元素访问7. vector的修改8. vector<vector\<int\>>的使用9. vector的使用10. 模拟实现vector11. 迭代器失效11.1 insert插入数据内部迭代器失效11.2 insert插入…

GPT 结束语设计 以nanogpt为例

GPT 结束语设计 以nanogpt为例 目录 GPT 结束语设计 以nanogpt为例 1、简述 2、分词设计 3、结束语断点 1、简述 在手搓gpt的时候&#xff0c;可能会遇到一些性能问题&#xff0c;即关于是否需要全部输出或者怎么节约资源。 在输出语句被max_new_tokens 限制&#xff0c…

PTMD2.0-疾病相关的翻译后修饰数据库

翻译后修饰&#xff08;PTMs&#xff0c;post-translational modifications&#xff09;通过调节蛋白质功能参与了几乎所有的生物学过程&#xff0c;而 PTMs 的异常状态常常与人类疾病相关。在此&#xff0c;PTMD 2.0展示与疾病相关的 PTMs 综合数据库&#xff0c;其中包含 93 …

ArcGIS10.2 许可License点击始终启动无响应的解决办法及正常启动的前提

1、问题描述 在ArcGIS License Administrator中&#xff0c;手动点击“启动”无响应&#xff1b;且在计算机管理-服务中&#xff0c;无ArcGIS License 或者License的启动、停止、禁止等均为灰色&#xff0c;无法操作。 2、解决方法 ①通过cmd对service.txt进行手动服务的启动…

spring框架之IoC学习与梳理(1)

目录 一、spring-IoC的基本解释。 二、spring-IoC的简单demo&#xff08;案例&#xff09;。 &#xff08;1&#xff09;maven-repository官网中找依赖坐标。 &#xff08;2&#xff09;.pom文件中通过标签引入。 &#xff08;3&#xff09;使用lombok帮助快速开发。 &#xff…

系统架构设计师教材:信息系统及信息安全

信息系统 信息系统的5个基本功能&#xff1a;输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段&#xff0c;即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则&#xff1a;只有高层管理人员才能知道企业究竟需要什么样的信…

基于STM32单片机设计的宠物喂食监控系统

1. 项目开发背景 随着宠物数量的增加&#xff0c;尤其是人们对宠物的养护需求日益增多&#xff0c;传统的人工喂养和管理方式难以满足现代养宠生活的需求。人们越来越希望通过智能化手段提高宠物养护的质量和效率&#xff0c;特别是对于宠物喂食、饮水、温湿度控制等方面的智能…

帕金森患者:科学锻炼,提升生活质量

帕金森病&#xff0c;作为一种常见的神经系统退行性疾病&#xff0c;给患者的日常生活带来了诸多挑战。然而&#xff0c;通过科学的锻炼&#xff0c;患者不仅可以在一定程度上缓解症状&#xff0c;还能提升生活质量。本文将详细介绍帕金森患者应该进行的几种关键锻炼&#xff0…

GA-CNN-LSTM-Attention、CNN-LSTM-Attention、GA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比

GA-CNN-LSTM-Attention、CNN-LSTM-Attention、GA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比 目录 GA-CNN-LSTM-Attention、CNN-LSTM-Attention、GA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于GA-CNN-LST…

redis 实践与扩展

文章目录 前言一、springboot整合redis1、jedis1.1、单点模式1.2、哨兵模式1.3 集群模式1.4、关于jedis线程不安全的验证 2、lettuce(推荐)2.1、单点模式2.2、哨兵模式2.3、集群模式 3、RedisTemplate config 二、redis常用知识点1、缓存数据一致性2、缓存雪崩3、缓存击穿4、缓…

積分方程與簡單的泛函分析7.希爾伯特-施密特定理

1)def函數叫作"由核生成的(有源的)" 定义: 设 是定义在区域上的核函数。 对于函数,若存在函数使得, 则称函数是“由核生成的(有源的)”。 这里的直观理解是: 函数的“来源”可以通过核函数 与另一个函数的积分运算得到。 在积分方程理论中,这种表述常…