邮件发送在实际业务中的使用

简介: 在前面的文章里有介绍过hutool工具的邮件发送,但是在实际的业务中并不是调用其sendMail方法就能实现业务的,有时候我们得对其进行改造或者自己写方法实现,那今天来看看我是如何实现发送邮件及多个附件功能的。

微信截图_20220531150923.png


前言


在前面的文章里有介绍过hutool工具的邮件发送,但是在实际的业务中并不是调用其sendMail方法就能实现业务的,有时候我们得对其进行改造或者自己写方法实现,那今天来看看我是如何实现发送邮件及多个附件功能的。


一.实现思路

先实现动态Excel实现再实现邮件发送多人及多附件,动态生成Excel的是因为业务需要的Excel表格数据可能会根据后期的需要增加或减少字段,所以不能固定,可以通过SQL查询出来然后根据字段创建动态表头和对应的数据列,其次是发送邮件时需要发送多个附件,如果是先生成到本地再从本地取到再作为附件发送有点不太好,可以用数据流的方式发送生成的Excel文件,这个点也是行得通的,那下面来看看具体的实现吧。


二.具体实现


1.生成动态Excel


1)动态表头生成

/***
 * 动态创建表头 
 * @param map 
 * @return
 */
public static String[] createTitle(Map<String, Object> map) {
    int count = 0;
    String strings[] = new String[map.size()];
    for( Map.Entry<String, Object> entry : map.entrySet() ) {
        strings[count] = entry.getKey();
        count++;
    }
    return strings;
}
复制代码


2)绘制Excel,包括表头以及数量类型的一些简单处理

/**
     * 创建Excel
     * @param sheetName sheet名称
     * @param title     标题
     * @param values    内容
     * @param wb        HSSFWorkbook对象
     * @return
     */
    public static HSSFWorkbook createHSSFWorkbook(String sheetName, String[] title, String[][] values, HSSFWorkbook wb) {
        // 第一步,创建一个HSSFWorkbook,对应一个Excel文件
        if (wb == null) {
            wb = new HSSFWorkbook();
        }
        // 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
        HSSFSheet sheet = wb.createSheet(sheetName);
        // 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制
        HSSFRow row = sheet.createRow(0);
        // 第四步,创建单元格,并设置值表头 设置表头居中
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
        //声明列对象
        HSSFCell cell = null;
        //创建标题
        for (int i = 0; i < title.length; i++) {
            cell = row.createCell(i);
            cell.setCellValue(title[i]);
            cell.setCellStyle(style);
        }
        HSSFCellStyle contextstyle =wb.createCellStyle();
        //创建内容
        for (int i = 0; i < values.length; i++) {
            row = sheet.createRow(i + 1);
            for (int j = 0; j < values[i].length; j++) {
                Boolean isNum = false;
                Boolean isInteger=false;//data是否为整数
                HSSFCell contentCell = row.createCell(j);
              //将内容按顺序赋给对应的列对象
                if (null!=values[i][j] || "".equals(values[i][j])) {
                    //判断data是否为数值型
                    isNum = values[i][j].toString().matches("^(-?\d+)(\.\d+)?$");
                    //判断data是否为整数(小数部分是否为0)
                    isInteger=values[i][j].toString().matches("^[-\+]?[\d]*$");
                }
                // 此处设置数据格式
                if (isNum) {
                    HSSFDataFormat df = wb.createDataFormat(); 
                    if (isInteger) {
                    //数据格式只显示整数
                     contextstyle.setDataFormat(df.getBuiltinFormat("#,#0"));
                    }else{
                    /保留一位小数点
                     contextstyle.setDataFormat(df.getBuiltinFormat("#,##0.0"));/
                    }
                    // 设置单元格格式
                    contentCell.setCellStyle(contextstyle);
                    // 设置单元格内容为double类型
                    contentCell.setCellValue(Double.parseDouble(values[i][j]));
                } else {
                    contentCell.setCellStyle(contextstyle);
                    // 设置单元格内容为字符型
                    contentCell.setCellValue(values[i][j]);
                }
            }
            //设置自动列宽
            sheet.autoSizeColumn(i);
            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);
        }
        return wb;
    }
复制代码


3)组装数据,将MySQL里查询的数据,组整到一个List>里,为什么是LinkedHashMap而不是Map,这里有一个小细节,MySQL查询出来不一定按照数据库看到的顺序,所以得使用LinkedHashMap去接收,即将其变成有顺的

微信截图_20220531151000.png

2.发送邮件


1)发送多人及多个附件

/**
 * @param subject 邮件标题
 * @param mapList 附件信息 可多附件
 * @param content 邮件内容
 * @param receiveList 收件人集合
 */
public static void sendEmail(String subject, List<Map<String,Object>> mapList, String content, List<String> receiveList, String smtpHost, String userName, String password) {
    logger.info("send report start>>>>>>>>>>>>");
    Session session = EmailUtils.getSession(smtpHost, userName, password);
    MimeMessage message = new MimeMessage(session);
    InternetAddress[] toArray = new InternetAddress[receiveList.size()];
    try {
        //接收列表
        for (int i = 0; i < toArray.length; i++) {
            toArray[i] = new InternetAddress(receiveList.get(i));
        }
        message.setSubject(subject);
        message.setSentDate(new Date());
        message.setFrom(new InternetAddress(userName));
        message.addRecipients(MimeMessage.RecipientType.TO, toArray);
        // 创建消息部分
        BodyPart messageBodyPart = new MimeBodyPart();
        // 消息
        messageBodyPart.setContent(content, "text/html;charset=utf-8");
        // 创建多重消息及可以发送多个附件
        Multipart multipart = new MimeMultipart();
        // 设置文本消息部分
        multipart.addBodyPart(messageBodyPart);
        //添加附件 这里以流形式直接发送
        for (Map<String, Object> map : mapList) {
            messageBodyPart = new MimeBodyPart();
            DataSource source = new ByteArrayDataSource((byte[])map.get("os"), "application/excel");
            messageBodyPart.setDataHandler(new DataHandler(source));
            //避免中文乱码的处理
            messageBodyPart.setFileName(MimeUtility.encodeText(map.get("title") + ".xlsx"));
            multipart.addBodyPart(messageBodyPart);
        }
        // 发送完整消息
        message.setContent(multipart);
        // 发送消息
        Transport.send(message);
        logger.info("send email successful>>>>>>>>>>>>");
    } catch (Exception e) {
        e.printStackTrace();
        logger.error("send email error",e.getMessage());
    }
}
复制代码


2)发送结果及数据,@1为目标邮件收到邮件的截图,@2为测试数据,@2中箭头标注的就是SQL里的字段,直接查询出中文然后通过createTitle创建表头,并根据其长度生成对应的列


@1微信截图_20220531151031.png

@2微信截图_20220531151112.png2)关于收件人配置

这里收件人可以配置到数据库或者Redis,需要添加或者删除改了立即生效,因为也不是常用的,没有必要放到配置文件里。


三.常见报错及解决


1.明明已开启SMTP但是过段时间后报了@1的错误,解决办法。重新生成授权码@2并替换之前设置的密码,此处是新浪邮箱为示例。


@1

网络异常,图片无法展示
|


@2微信截图_20220531151136.png


小结


很多人估计在拿到需求的时候就开始写代码,其实这样写出来的代码质量并不高,拿到需求应该先打个草稿或者画个图应该怎么处理,再怎么处理,代码虽然都是改出来的,后者的效率肯定要高很多,还有就是开发的时候能写灵活方法就写灵活的,别只顾着当前业务实现就行了。另外因为篇幅的限制,部分代码只能是截图的方式展示。

目录
相关文章
|
5月前
|
数据安全/隐私保护
邮件发送的原理,如何进行邮件发送
邮件发送的原理,如何进行邮件发送
|
3月前
|
JSON API 数据安全/隐私保护
阿里云邮件推送邮件发送失败的问题排查解决
阿里云邮件推送服务中邮件发送失败的排查方法包括:确认SMTP设置正确无误;验证发信域名和邮件地址;检查是否超出发送配额;审查邮件内容以确保合规;确保网络连接稳定;利用发送日志诊断具体问题。当阿里云邮件推送服务出现问题时,可考虑使用AOKSend作为替代方案,其配置简单且服务稳定可靠,支持多种配置选项,并提供详尽的文档支持。示例Python代码展示了如何使用AOKSend API发送邮件。这些步骤有助于确保邮件的顺利发送。
|
4月前
|
安全 API 数据安全/隐私保护
发送邮件API接口有哪些平台?
在数字化时代,企业借助邮件发送API如AokSend、Mailgun、Amazon SES、Postmark和Sendinblue自动化邮件发送。这些平台提供高可靠性、灵活性、扩展性和多功能集成,支持邮件营销、事务邮件和客户沟通。例如,AokSend以其丰富的功能和易集成著称,而Mailgun则适合需要高级功能的开发者。Amazon SES以高扩展性和经济实惠吸引快速增长的企业,Postmark专长于快速的事务性邮件,Sendinblue则结合了邮件和短信营销。每个平台都有相应的Python示例代码展示如何使用其API发送邮件。
人事管理项目-配置邮件发送
人事管理项目-配置邮件发送
|
SQL 关系型数据库 MySQL
独角数卡 搭建-邮件配置-Epusdt配置-收U详细配置
独角数卡 搭建-邮件配置-Epusdt配置-收U详细配置
1698 0
|
消息中间件 Java RocketMQ
支付业务服务端测试|学习笔记
快速学习支付业务服务端测试
111 0
支付业务服务端测试|学习笔记
|
开发者
消息服务-短信产品规则和业务限制 | 学习笔记
快速学习消息服务-短信产品规则和业务限制
281 0
|
存储 网络协议 数据安全/隐私保护
基于163邮箱实现的邮件发送功能
基于163邮箱实现的邮件发送功能
477 0
基于163邮箱实现的邮件发送功能
|
运维 数据安全/隐私保护 C++
阿里云禁止25端口,使用465端口发送运维邮件
阿里云禁止25端口,使用465端口发送运维邮件
11265 0