Springboot 使用JavaMailSender发送邮件 + Excel附件

这篇具有很好参考价值的文章主要介绍了Springboot 使用JavaMailSender发送邮件 + Excel附件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.生成Excel表格

1.依赖设置

2.代码:

2.邮件发送

1.邮件发送功能实现-带附件

 2.踩过的坑

1.附件名中文乱码问题

3.参考文章:


需求描述:项目审批完毕后,需要发送邮件通知相关人员,并且要附带数据库表生成的Excel表格,这就要求不光是邮件发送功能,还要临时生成Excel表格做为附件

1.生成Excel表格

使用huTool工具包的Excel表格生成功能

1.依赖设置

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.22</version>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.2</version>
</dependency>

Hutool-all中包含了Hutool的所有工具类,由于需要生成Excel文件需要依赖poi

2.代码:

要加try finally,在finally将输出流和其他需要关闭的都进行关闭,防止发生内存泄漏 

    @Override
    public void publish(xxxxxxPublishVo publishVo) {
        ....................................................
        /**
         * 生成Excel表格
         */
        //在内存操作,写到输出流中
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //自定义标题别名
        writer.addHeaderAlias("projectCode", "项目编号");
        writer.addHeaderAlias("projectName", "项目名称");
        writer.addHeaderAlias("targetType", "指标类型");
        writer.addHeaderAlias("targetName", "指标名称");
        writer.addHeaderAlias("targetForMp", "转量产品质目标");
        writer.addHeaderAlias("symbols", "目标限制符");

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try{
            //获取数据
            Qpm******Mg query = new Qpm******Mg();
            query.setProjectCode(publishVo.getProjectCode());
            List<Qpm******MGListDTO> data = selectQpm******MgByCondition(query);

            //整理数据,以便于生成Excel表格
            List<Object> dataNew = new ArrayList<>();
            Set<String> stageCollectSet = new HashSet<>();
            //后续排序的时候需要使用
//        List<Qpm******MgStage> noRepeatList = new ArrayList<>();
            //先获取所有的阶段:D*T,E*T等
            for (Qpm******MGListDTO target : data) {
                List<Qpm******MgStage> stageList = target.get******StageList();
                for (Qpm******MgStage stage : stageList) {
                    if (!stageCollectSet.contains(stage.getStage())) {
                        stageCollectSet.add(stage.getStage());

                        //给Excel增加列
                        writer.addHeaderAlias(stage.getStage(), stage.getStage() + "目标");
                    }
                }
            }
            //处理Excel表格数据
            for (Qpm******MGListDTO target : data) {
                List<Qpm******MgStage> stageList = target.get******StageList();
                Map<String, Object> addProperties = new HashMap<>();
                for (String stageStr : stageCollectSet) {
                    addProperties.put(stageStr, "");
                }
                for (Qpm******MgStage stage : stageList) {
                    //为对象动态增加属性
                    //这里要处理值为null的情况
                    if(null == stage.getxxxTarget()){
                      addProperties.put(stage.getStage(), "");
                    }else{
                      addProperties.put(stage.getStage(), stage.getxxxTarget());
//                        noRepeatList.add(stage);
                    }
                }

                //生成新的包含了新增字段的对象
                Object targetNew = ReflectUtil.getTarget(target, addProperties);
                dataNew.add(targetNew);
            }

            //只保留别名的数据
            writer.setOnlyAlias(true);
            writer.write(dataNew, true);
            // excel写入输出流
            writer.flush(outputStream, true);
        ...........................................................................

上述代码中,调用了工具类ReflectUtil给对象动态增加属性。由于数据中有子类,需要获取到子类中的某个字段并生成Excel表格,所以Excel表格构造就需要对数据对象进行改造,简单来说就是需要给对象动态增加新的属性(成员对象的属性),如下所示示例:

把studentList里面的关键属性数据,新增给Test类

示例不是很合适,凑合着用吧

class Test {

    private String class;

    .............................................

    private List<Student> studentList;

}

工具类ReflectUtil,用于给对象动态增加新的属性:

import com.google.common.collect.Maps;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 为实体类动态增加属性,用于生成Excel表格时的特殊情况,例如表格中的列需要动态增加
 */
public class ReflectUtil {
    static Logger logger = LoggerFactory.getLogger(ReflectUtil.class);

    public static Object getTarget(Object dest, Map<String, Object> addProperties) {
        // get property map
        PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
        PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest);
        Map<String, Class> propertyMap = Maps.newHashMap();
        for (PropertyDescriptor d : descriptors) {
            if (!"class".equalsIgnoreCase(d.getName())) {
                propertyMap.put(d.getName(), d.getPropertyType());
            }
        }
        // add extra properties
        for (Map.Entry<String, Object> entry : addProperties.entrySet()) {
            propertyMap.put(entry.getKey(), entry.getValue().getClass());
        }
//        addProperties.forEach((k, v) -> propertyMap.put(k, v.getClass()));
        // new dynamic bean
        DynamicBean dynamicBean = new DynamicBean(dest.getClass(), propertyMap);
        // add old value
        for (Map.Entry<String, Class> entry : propertyMap.entrySet()) {
            try {
                // filter extra properties
                if (!addProperties.containsKey(entry.getKey())) {
                    dynamicBean.setValue(entry.getKey(), propertyUtilsBean.getNestedProperty(dest, entry.getKey()));
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        ;
        // add extra value
        for (Map.Entry<String, Object> entry : addProperties.entrySet()) {
            try {
                dynamicBean.setValue(entry.getKey(), entry.getValue());
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        ;
        Object target = dynamicBean.beanMap;
        return target;
    }

    public static class DynamicBean {
        /**
         * 目标对象
         */
        private Object target;

        /**
         * 属性集合
         */
        private BeanMap beanMap;

        public DynamicBean(Class superclass, Map<String, Class> propertyMap) {
            this.target = generateBean(superclass, propertyMap);
            this.beanMap = BeanMap.create(this.target);
        }


        /**
         * bean 添加属性和值
         *
         * @param property
         * @param value
         */
        public void setValue(String property, Object value) {
            beanMap.put(property, value);
        }

        /**
         * 获取属性值
         *
         * @param property
         * @return
         */
        public Object getValue(String property) {
            return beanMap.get(property);
        }

        /**
         * 获取对象
         *
         * @return
         */
        public Object getTarget() {
            return this.target;
        }


        /**
         * 根据属性生成对象
         *
         * @param superclass
         * @param propertyMap
         * @return
         */
        private Object generateBean(Class superclass, Map<String, Class> propertyMap) {
            BeanGenerator generator = new BeanGenerator();
            if (null != superclass) {
                generator.setSuperclass(superclass);
            }
            BeanGenerator.addProperties(generator, propertyMap);
            return generator.create();
        }
    }
}

至此,我们就生成了Excel表格,并且把数据写入到了输出流中。

下面我们需要从输出流中拿到Excel表格数据,并做为邮件的附件发送出去。

2.邮件发送

1.邮件发送功能实现-带附件

Spring Email 抽象的核心是 JavaMailSender接口,通过实现JavaMailSender接口把 Email 发送给邮件服务器,由邮件服务器实现邮件发送的功能。

Springboot 使用JavaMailSender发送邮件 + Excel附件,Java Web,Springboot,Spring,spring boot

Spring 自带了一个 JavaMailSender的实现 JavaMailSenderImpl。SpringBoot 应用在发送 Email 之前,我们需要在配置文件中对JavaMailSender进行属性配置,这样就可以利用Springboot的自动装配机制,将 JavaMailSenderImpl 装配为 Spring容器的一个 bean。

spring.mail.host: xxxxxxx.com
# 设置端口
spring.mail.port: 25
# 设置用户名
spring.mail.username: xxxxxxxxxx
# 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码
spring.mail.password: xxxxxxxxx
# 设置是否需要认证,如果为true,那么用户名和密码就必须的,
# 如果设置false,可以不设置用户名和密码,当然也得看你的对接的平台是否支持无密码进行访问的。
spring.mail.properties.mail.smtp.auth: false
# STARTTLS[1]  是对纯文本通信协议的扩展。它提供一种方式将纯文本连接升级为加密连接(TLS或SSL),而不是另外使用一个端口作加密通信。
spring.mail.properties.mail.smtp.starttls.enable: true
spring.mail.properties.mail.smtp.starttls.required: fasle
spring.mail.properties.mail.imap.starttls.socketFactory.fallback: false
spring.mail.properties.mail.smtp.starttls.socketFactory.class: com.ey.model.MailCommand

(完整代码) 继上面完整的Excel生成代码,现在继续写邮件发送代码:

    @Autowired
    private JavaMailSender springMailSender;    

    @Override
    public void publish(xxxxxxPublishVo publishVo) {
        /**
         * 生成Excel表格
         */
        //在内存操作,写到输出流中
        ExcelWriter writer = ExcelUtil.getWriter(true);
        //自定义标题别名
        writer.addHeaderAlias("projectCode", "项目编号");
        writer.addHeaderAlias("projectName", "项目名称");
        writer.addHeaderAlias("targetType", "指标类型");
        writer.addHeaderAlias("targetName", "指标名称");
        writer.addHeaderAlias("targetForMp", "转量产品质目标");
        writer.addHeaderAlias("symbols", "目标限制符");

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try{
            //获取数据
            Qpm******Mg query = new Qpm******Mg();
            query.setProjectCode(publishVo.getProjectCode());
            List<Qpm******MGListDTO> data = selectQpm******MgByCondition(query);

            //整理数据,以便于生成Excel表格
            List<Object> dataNew = new ArrayList<>();
            Set<String> stageCollectSet = new HashSet<>();
            //后续排序的时候需要使用
//        List<Qpm******MgStage> noRepeatList = new ArrayList<>();
            //先获取所有的阶段:D*T,E*T等
            for (Qpm******MGListDTO target : data) {
                List<Qpm******MgStage> stageList = target.get******StageList();
                for (Qpm******MgStage stage : stageList) {
                    if (!stageCollectSet.contains(stage.getStage())) {
                        stageCollectSet.add(stage.getStage());

                        //给Excel增加列
                        writer.addHeaderAlias(stage.getStage(), stage.getStage() + "目标");
                    }
                }
            }
            //处理Excel表格数据
            for (Qpm******MGListDTO target : data) {
                List<Qpm******MgStage> stageList = target.get******StageList();
                Map<String, Object> addProperties = new HashMap<>();
                for (String stageStr : stageCollectSet) {
                    addProperties.put(stageStr, "");
                }
                for (Qpm******MgStage stage : stageList) {
                    //为对象动态增加属性
                    addProperties.put(stage.getStage(), stage.getStageTarget());
//                        noRepeatList.add(stage);
                }

                //生成新的包含了新增字段的对象
                Object targetNew = ReflectUtil.getTarget(target, addProperties);
                dataNew.add(targetNew);
            }

            //只保留别名的数据
            writer.setOnlyAlias(true);
            writer.write(dataNew, true);
            // excel写入输出流
            writer.flush(outputStream, true);
			
            //这个地方无需再配置,springboot自动装配,配置信息在nacos配置中心
//            springMailSender.setDefaultEncoding("UTF-8");
//            springMailSender.setHost("mx.goertek.com");
//            springMailSender.setPort(25);
//            springMailSender.setProtocol(JavaMailSenderImpl.DEFAULT_PROTOCOL);
//            springMailSender.setUsername("tims.sys@goertek.com");
//            springMailSender.setPassword("Khkd0804");
//            Properties p = new Properties();
//            p.setProperty("mail.smtp.timeout", "25000");
//            p.setProperty("mail.smtp.auth", "true");
//            p.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//            springMailSender.setJavaMailProperties(p);

            MimeMessage mimeMessage = springMailSender.createMimeMessage();
            System.getProperties().setProperty("mail.mime.splitlongparameters", "false");
            MimeMessageHelper messageHelper = null;
            messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
//            LoginUser userInfo = UserUtil.getCurrentUser();
//            String currentUserEmail = userInfo.getEmaila();
//            messageHelper.setFrom(currentUserEmail);
            messageHelper.setFrom(mailUserName);

            //设置收件人
            String[] emailArr = publishVo.getEmails().replaceAll("\\s+", "").split(",");
            messageHelper.setTo(emailArr);

            //设置抄送人
            if (!StringUtils.isBlank(publishVo.getCcEmails())){
                String[] ccEmailArr = publishVo.getCcEmails().replaceAll("\\s+", "").split(",");
                messageHelper.setCc(ccEmailArr);
            }

            messageHelper.setSubject("【G**S通知】项目-" + publishVo.getProjectName().concat(": 制定**目标完毕"));
            if (StringUtils.isEmpty(publishVo.getContent())){
                messageHelper.setText("项目-" + publishVo.getProjectName().concat(": 制定**目标完毕"));
            }else {
                messageHelper.setText(publishVo.getContent());
            }
            //messageHelper.addInline("doge.gif", new File("xx/xx/doge.gif"));
            messageHelper.addAttachment(MimeUtility.encodeWord(fileName,"utf-8","B"), new ByteArrayResource(outputStream.toByteArray()));

            springMailSender.send(mimeMessage);
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭writer,释放内存,防止内存泄漏
            writer.close();

            //关闭输出流,防止内存泄漏
            try {
                if(null != outputStream) {
                    outputStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

 2.踩过的坑

上述邮件发送功能实现过程中踩过的坑:

1.附件名中文乱码问题

附件的名字是中文,发送成功后,在邮件中的附件名字中文乱码,怎样解决这个问题?

1. 设置系统值:

System.setProperty("mail.mime.splitlongparameters", "false");

2. 这里,在创建对象的时候定义编码格式(utf-8):

MimeMessageHelper messageHelper = new MimeMessageHelper(mes, true, "utf-8");

3. 其次,在添加附件的时候,附件名是需要定义编码:

messageHelper.addAttachment(MimeUtility.encodeWord(附件名,"utf-8","B"), 附件输入流));

3.参考文章:

使用hutool工具进行导入导出excel表格_hutool excel-CSDN博客

springboot:实现excel生成并且通过邮件发送 - 哔哩哔哩

重要: Hutool Java 工具类库Excel导出,配置宽度自适应极度舒适_hutool导出excel设置列宽_夜雨微澜醉挽清风的博客-CSDN博客 文章来源地址https://www.toymoban.com/news/detail-731594.html

到了这里,关于Springboot 使用JavaMailSender发送邮件 + Excel附件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何使用JavaMailSender给曾经心爱的她发送一封特别的邮件

    网站的服务端向用户发邮件时,邮件中往往需要携带图片,链接等内容。所以为了方便起见,我们一般发送HTML格式的邮件,那么怎么去拼一个HTML格式的邮件呢?——Thymeleaf。 开始之前,先新建一个SpringBoot项目,并添加需要用到的依赖。然后就可以继续往下了。 首先我们需

    2023年04月18日
    浏览(27)
  • springboot 发送邮件,以及邮件工具类 并且解决spring-boot-starter-mail 发送邮件附件乱码或者文件错乱

    1、设置系统值 System.setProperty(“mail.mime.splitlongparameters”, “false”); 2、 在创建对象的时候定义编码格式(utf-8): MimeMessageHelper helper = new MimeMessageHelper(mes, true, “utf-8”); 3、 其次,在添加附件的时候,附件名是需要定义编码的 helper.addAttachment(MimeUtility.encodeWord(附件名,“utf-8”

    2024年02月15日
    浏览(41)
  • springboot(java)使用javamail实现邮件的接收、转发、发送、清除

    最近在弄邮件相关的功能,被搞的头大,很多找的方法根本不知道该怎么往下走,就目前为止, 经过各种的碰壁和失败,就整理出来如何使用javamail实现邮件的接收、转发、发送、清除 不单单是分享,也为我后续查找更方便做一个记录 在正式发送邮件之前,我们应该对邮件

    2024年02月04日
    浏览(30)
  • 无缓存定时发送带附件(表格)等邮件

    1.导入发送邮件的包 2.配置yml 3.添加定时任务 4.实现

    2024年02月11日
    浏览(29)
  • Spring Boot邮件发送教程:步步为营,轻松实现图片附件邮件!

      通过Spring Boot构建一个功能强大的邮件发送应用程序,重点是实现发送包含图片附件的邮件。我将逐步介绍添加必要的依赖、创建邮件服务类和控制器的步骤,并提供了具体的示例源代码。跟随这个简单而清晰的教程,您将能够轻松地集成邮件发送功能到您的Spring Boot应用中

    2024年02月04日
    浏览(35)
  • python提取邮件的附件,以excel为例

    配置邮箱、读取基本的邮件内容请参考:python读取并解析邮箱邮件,读取邮件主题、内容、时间 以excel为例: 获取邮件: 提取数据需要使用: 写入本地文件时,使用:

    2024年02月10日
    浏览(29)
  • c++实现smtp发送邮件,支持ssl的465端口发送,支持附件、一次发送多人、抄送等

    c++实现smtp发送邮件,支持ssl的465端口发送,支持附件、一次发送多人、抄送等。 这里只使用了openssl库(用来支持ssl的465端口),其他部分是原生c++,支持在win/linux运行。 网上很多都是原始的支持25端口,明文发送,这里介绍一下ssl思路 使用sockect编程和ssl,使用SMTP协议。 使

    2024年02月08日
    浏览(68)
  • 让自己开发的VBA应用能够批量发送邮件(可带多个附件)

    当我们开发了一个VBA应用,很多时候需要让它能够自动批量发送邮件。这时候,我们就需要使用到CDO了。CDO全称Collaboration Data Objects,即协作数据对象,是Office 软件不在产品安装的一部分。它是通过基于COM的API提供对Outlook兼容对象的访问的包。CDO有多个组件,其中Message组件

    2024年02月11日
    浏览(27)
  • 邮件发送,附件太大怎么办 → 那就用分卷压缩吧

    昨晚,老婆辅导女儿写作业 有一道形容妈妈的题,女儿写下了:我妈妈像一个暴躁的老虎 老婆拿起题册轻轻敲了下女儿,生气到:有这么形容你妈的吗 女儿:你看你现在 老婆:我有那么暴躁吗,你就不能说我妈妈像一个公主,温柔大方漂亮? 女儿:题目让我造句,没让我

    2024年02月08日
    浏览(77)
  • 泛微OA获取流程附件地址,发送邮件或上传到第三方系统中

    在泛微的流程开发当中,有些流程的数据、附件要上传到其它平台,与其它平台相互集成对接, 一般是在写Action事件时,就会自动把数据及附件上传到其它平台,以下内容是经过正常使用获取流程附件的业务 示例:泛微OA中流程附件

    2024年02月15日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包