Springboot实现定时发送邮件、附件实现代码

该博客介绍了如何在Spring Boot中配置并使用邮件服务,包括添加依赖、配置邮箱信息以及编写邮件配置类。同时,展示了如何设置定时任务来周期性地发送邮件,包括编写定时任务类和邮件服务接口及其实现。最后,详细展示了邮件发送的具体实现,包括创建Excel文件作为附件并发送。
摘要由CSDN通过智能技术生成

首先在pom.xml文件添加如下依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<dependency>
	<groupId>com.sun.mail</groupId>
	<artifactId>javax.mail</artifactId>
</dependency>

其次编写application.properties文件进行邮箱信息配置,如添加如下内容:

####邮件系统参数设置开始

#邮件服务器地址
spring.mail.host=smtp.exmail.qq.com

#邮件服务器端口
spring.mail.port=465

#邮件服务器登录用户名、密码(此处是企业邮箱)
#登录密码,开通腾讯企业邮箱后,必须修改原密码,否则会报发送异常(501 ÇëµÇ¼exmail.qq.comÐÞ¸ÄÃÜÂë );
#企业邮箱如果未开启安全登录,就不需要授权码了,直接填写登录密码即可。如果开启了安全登录,则这里需要填写客户端专用密码,即授权码
spring.mail.username=occ@hanhoo.com
#如果这不是企业邮箱,是个人邮箱,则此处需要填写授权码而不是密码
#spring.mail.password=5VW9UW5S5eQUBigy
spring.mail.password=123456

spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8

#开户验证身份 true/false
spring.mail.properties.mail.smtp.auth=true

spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.ssl.enable=true

spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socketFactory.class.fallback=false

#邮件发送地址(此处是企业邮箱)
spring.mail.send.from=occ@hanhoo.com

#邮件接收地址(此处是企业邮箱)
spring.mail.send.to={ dd@hanhoo.com, cc@hanhoo.com }

#邮件抄送地址(此处是企业邮箱)
spring.mail.send.cc=aa@hanhoo.com

####邮件系统参数结束

个人邮箱授权码获取,这里以qq邮箱为例,如图:
打开qq邮箱,点击设置
在这里插入图片描述
选择账户:
在这里插入图片描述
拉到下面开启smpt服务,需要短信开通:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

写一个邮箱配置类:

package com.yonyou.occ.report.config;

import com.sun.mail.util.MailSSLSocketFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.security.GeneralSecurityException;
import java.util.Properties;

/**
 * @author 
 * @date 2020-11-23 11:22
 */
@Configuration
public class MailSenderConfig implements WebMvcConfigurer {


    //登录用户名
    @Value("${spring.mail.username}")
    private String username;

    //登录密码,开通腾讯企业邮箱后,必须修改原密码,否则会报发送异常(501 ÇëµÇ¼exmail.qq.comÐÞ¸ÄÃÜÂë );
    // 企业邮箱如果未开启安全登录,就不需要授权码了,直接填写登录密码即可。如果开启了安全登录,则这里需要填写客户端专用密码,即授权码
    @Value("${spring.mail.password}")
    private String password;

    //发送服务器地址
    @Value("${spring.mail.host}")
    private String host;

    //端口
    @Value("${spring.mail.port}")
    private Integer port;

    //协议
    @Value("${spring.mail.protocol}")
    private String protocol;


    @Bean
    public JavaMailSenderImpl mailSender() {
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setUsername(username);
        javaMailSender.setPassword(password);
        javaMailSender.setHost(host);
        javaMailSender.setPort(port);
        javaMailSender.setProtocol(protocol);
        javaMailSender.setDefaultEncoding("UTF-8");
        Properties props = new Properties();//②
        props.setProperty("mail.smtp.host", host);
        props.setProperty("mail.smtp.auth", "true");
        //使用SSL,企业邮箱必需!
        //开启安全协议
        MailSSLSocketFactory sf = null;
        try {
            sf = new MailSSLSocketFactory();
            sf.setTrustAllHosts(true);
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        props.put("mail.smtp.ssl.enable", "true");
        props.put("mail.smtp.ssl.socketFactory", sf);
        props.put("mail.smtp.ssl.socketFactory.fallback", "false");

        Session session = Session.getInstance(props, new MailAuthenricator(username, password));
        session.setDebug(Boolean.TRUE);
        javaMailSender.setSession(session);//③
        return javaMailSender;
    }

    //用户名密码验证,需要实现抽象类Authenticator的抽象方法PasswordAuthentication
    static class MailAuthenricator extends Authenticator {
        String u = null;
        String p = null;

        public MailAuthenricator(String u, String p) {
            this.u = u;
            this.p = p;
        }

        @Override
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(u, p);
        }
    }
}

编写定时任务类:

package com.yonyou.occ.report.task;

import com.yonyou.occ.report.service.EmailSendService;
import com.yonyou.ocm.common.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 
 * @date 2020-11-20 10:06
 */
@Slf4j
@Component
//@Async //可加在类或方法,开启异步事件的支持
public class ExportDataSchedulerTask {

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private EmailSendService emailSendService;

    //cron表达式:0 0 0 1 * ? ,表示每月的1号零点零分零秒执行一次
    @Scheduled(cron = "0 0 0 1 * ?")
    //cron表达式:0 */1 * * * ?,表示每一分钟执行一次
	//@Scheduled(cron = "0 */1 * * * ?")
    public void scheduled() {
        long startTime = System.currentTimeMillis();
        log.info("--------------  开始 执行导出【客户活动明细报表】数据定时任务 start --------------------" + startTime);

        Map<String, Object> searchParams = new HashMap<>();

        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());

        //开始日期减一年
        cal.add(Calendar.YEAR, -1);
        String startDate = DateUtil.from_Date_to_String(DateUtil.yyMMddHHmmss, cal.getTime());

        //结束日期加一年
        cal.add(Calendar.YEAR, 1);
        String endDate = DateUtil.from_Date_to_String(DateUtil.yyMMddHHmmss, cal.getTime());

        searchParams.put("beginDate", startDate);
        searchParams.put("endDate", endDate);

        emailSendService.sendMail(searchParams, response);

        long endTime = System.currentTimeMillis();
        log.info("--------------  结束 执行导出【客户活动明细报表】数据定时任务 end --------------------" + (endTime - startTime) + "ms");
    }

}

编写接口:

package com.yonyou.occ.report.service;

import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @author 
 * @date 2020-11-20 19:03
 */
public interface EmailSendService {

    /**
     * 根据参数发送邮件
     * @param searchParams
     * @param response
     */
    void sendMail(Map<String, Object> searchParams, HttpServletResponse response);
}

编写接口实现类:

package com.yonyou.occ.report.service.impl;

import cn.hutool.poi.excel.ExcelUtil;
import com.yonyou.occ.report.service.EmailSendService;
import com.yonyou.occ.report.utils.BeanConverterUtils;
import com.yonyou.occ.report.vo.CustomerPromActivityDetailVO;
import com.yonyou.ocm.common.utils.DateUtil;
import jxl.Workbook;
import jxl.format.Colour;
import jxl.format.UnderlineStyle;
import jxl.write.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 
 * @date 2020-11-23 9:56
 */
@Slf4j
@Service
public class EmailSendServiceImpl implements EmailSendService {


    /**
     * 将邮件工具放入容器
     */
    private JavaMailSenderImpl mailSenderImpl;

    @Autowired
    public void setMailSenderImpl(JavaMailSenderImpl mailSender) {
        this.mailSenderImpl = mailSender;
    }

    @Autowired
    private CustomerPromActivityDetailServiceImpl customerPromActivityDetailServiceImpl;

    /**
     * 定义模板文件所在的相对路径, File.separator表示文件分隔符,可自动适配Windows和Linux系统
     */
    private static String PATH = "." + File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "templates" + File.separator;

    //发件人邮箱地址
    @Value("${spring.mail.send.from}")
    private String mailSendFrom;

    //收件人邮箱地址
    @Value("${spring.mail.send.to}")
    private String mailSendTo;

    //抄送人邮箱地址
    @Value("${spring.mail.send.cc}")
    private String mailSendCc;


    /**
     * 根据参数发送邮件
     *
     * @param searchParams
     * @param response
     */
    @Override
    public void sendMail(Map<String, Object> searchParams, HttpServletResponse response) {
        try {

            String dateStr = DateUtil.from_Date_to_String(DateUtil.yyMMddHHmmss, new Date());

            List<CustomerPromActivityDetailVO> customerPromActivityDetailVOS = customerPromActivityDetailServiceImpl.exportExcelData(searchParams, response);

            if (!StringUtils.isEmpty(customerPromActivityDetailVOS)) {

                List<Map<String, Object>> listMap = BeanConverterUtils.listConvert(customerPromActivityDetailVOS);

               StringBuilder fileName = new StringBuilder();
                // 表格名字
                String name = "客户活动明细报表_" + dateStr;

                fileName.append(name).append(".xls");

                String filePath = PATH + fileName.toString();

                File file = new File(filePath);
                // 文件为空则进行创建
                if (!file.exists()) {
                    //先得到文件的上级目录,并创建上级目录,在创建文件
                    file.getParentFile().mkdir();
                    try {
                        //创建文件
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                        log.info("--------------  临时文件创建失败 ----------------" + e.getMessage());
                    }
                }

                // 建立excel表格
                OutputStream os = new FileOutputStream(filePath);

                String[] titleArr = new String[] { "客户编码", "客户名称", "市场区域", "省份", "活动编码", "活动名称", "活动节点名称", "活动审批状态", "活动状态", "活动开始时间", "活动结束时间", "销售合同编码", "合同状态", "活动单位组金额", "收款单认领金额", "收款单认领组数", "授信组数", "授信额度", "活动明细行号", "促销规则编码", "促销规则名称", "规则描述", "活动促销方式", "产品组编码", "产品组名称", "控制类型", "项目类型", "行单位组数量", "行单位组金额", "合计", "零售价", "折扣", "价格", "边界值", "累计参加组数", "活动可提货组数", "活动可提货金额", "明细总金额", "累计行提货金额", "未提货金额", "实际未提货金额", "明细总数量", "累计行提货数量", "未提货数量", "实际未提货数量", "是否计任务", "是否计返点", "是否必选", "冻结值", "冻结金额", "未使用冻结金额", "已使用冻结金额", "是否关闭", "活动关闭回退金额", "货款余额", "零售价余额", "客户活动行备注" };
                String[] codeArr = new String[] { "customerCode", "customerName", "marketName", "provinceName", "activityCode", "activityName", "nodeName", "activityApproval", "activityStatusName", "startDate", "endDate", "ctCode", "ctStateName", "activityUnitGroupAmount", "totalClaimAmount", "claimGroup", "creditGroup", "creditLimit", "rowNum", "ruleCode", "ruleName", "ruleDesc", "ruleTypeName", "goodsCode", "goodsName", "controlTypeName", "projectType", "count", "amount", "total", "retailPrice", "rebate", "salePrice", "boundaryValue", "totalClaimGroup", "pickUpGroup", "pickUpAmount", "totalrowCtAmount", "totalrowOrderAmount", "notPickedUpAmount", "actualUndeliveredGoodsAmount", "totalrowCtNum", "totalrowOrderNum", "notPickedUpNum", "actualUndeliveredGoodsNum", "isCalTaskName", "isCalReturnName", "isRequireName", "freezeValue", "freezeAmount", "unuseFreezeAmount", "useFreezeAmount", "isCtClose", "returnAmount", "paymentBalance", "retailBalance", "lineRemark" };

                //导出数据到excel
                exportExcel(os, listMap, titleArr, codeArr, name);

                // 是否需要发邮件,根据配置是否为空来判断
                if (!mailSendTo.isEmpty()) {
                    // 将excel作为附件发送,并删除本地的excel文件
                    String subject = "客户活动明细报表";
                    String content = "你好,这是客户活动明细报表的数据,请查收!";

                    MimeMessage mailMessage = mailSenderImpl.createMimeMessage();
                    MimeMessageHelper messageHelper = new MimeMessageHelper(mailMessage, true, "utf-8");

                    // 发送方邮箱
                    messageHelper.setFrom(mailSendFrom);

                    // 接收方邮箱
                    if(mailSendTo.contains("{") && mailSendTo.contains("}")) {
                        String sendTo = mailSendTo.replace("{", "").replace("}", "");
                        String[] mailSendTos = sendTo.split(",");
                        messageHelper.setTo(mailSendTos);

                    } else if(mailSendTo.contains("{")) {
                        String sendTo = mailSendTo.replace("{", "");
                        String[] mailSendTos = sendTo.split(",");
                        messageHelper.setTo(mailSendTos);

                    } else if(mailSendTo.contains("}")){
                        String sendTo = mailSendTo.replace("}", "");
                        String[] mailSendTos = sendTo.split(",");
                        messageHelper.setTo(mailSendTos);

                    } else {
                        messageHelper.setTo(mailSendTo);
                    }


                    // 抄送方邮箱
                    messageHelper.setCc(mailSendCc);
                    // 设置邮件主题
                    messageHelper.setSubject(subject);
                    // 设置邮件主题内容
                    messageHelper.setText(content);

                    // 读取附件
                    FileSystemResource fileR = new FileSystemResource(new File(filePath));
                    // 这里的方法调用和插入图片是不同的。
                    // 设置附件
                    messageHelper.addAttachment(fileName + "", fileR);

                    long startTime = System.currentTimeMillis();
                    log.info("-----------------  发送邮件开始 -------------- " + startTime);
                    // 发送邮件
                    mailSenderImpl.send(mailMessage);
                    long endTime = System.currentTimeMillis();
                    log.info("-----------------  发送邮件成功,任务结束 --------------------  用时" + (endTime - startTime) + "ms");
                } else {
                    log.info("----------------- 发件邮箱或收件邮箱未配置,不发送报表数据邮件  --------------------");
                }


                // 路径为文件且不为空则进行删除
                if (file.isFile() && file.exists()) {
                    file.delete();
                    log.info("------------------  临时文件删除成功 --------------------");
                }
            }
        } catch (Exception e) {
            log.error("【客户活动明细报表】邮件发送异常:", e);
            e.printStackTrace();

        }

    }

    public static void exportExcel(OutputStream os, List<Map<String, Object>> list, String[] titleArr, String[] codeArr, String name){
        try {
            //创建一个工作簿,也就是整个文档
            WritableWorkbook wbook = Workbook.createWorkbook(os);
            //设置字体
            WritableFont wfont = new WritableFont(WritableFont.ARIAL, 10,
                    WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE,
                    Colour.BLACK);
            //定义单元格格式
            WritableCellFormat wcf = new WritableCellFormat(wfont);

            double maxSheetSize = 600000.0;
            int sheetNum = (int) Math.ceil(list.size() / maxSheetSize);
            for(int num = 0; num < sheetNum; num++){
                WritableSheet wsheet = wbook.createSheet(name + "("+(num+1)+")", num);

                String title=null;
                for(int i=0; i<titleArr.length; i++){
                    title = titleArr[i];
                    wsheet.addCell(new Label(i, 0, title, wcf));
                }
                for(int i = num*(int)maxSheetSize ; i < (num+1)*(int)maxSheetSize && i < list.size(); i++){
                    Map<String, Object> m = list.get(i);
                    int temp = i - num*(int)maxSheetSize + 1;
                    for(int j=0; j<codeArr.length; j++){
                        String value = String.valueOf(m.get(codeArr[j])==null?"":m.get(codeArr[j]));
                        wsheet.addCell(new Label(j, temp, value));
                    }
                }
            }

            wbook.write();
            wbook.close();
            os.close();
        }catch(Exception e){
            log.info("exception heppended in "+ ExcelUtil.class+" cause: ", e);
        }
    }

}

至此,邮箱发送功能实现到此结束。欢迎大佬们评论指导!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值