生成excel附件并发送email

1、pom

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

<!--commons-email-->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-email</artifactId>
	<version>1.5</version>
</dependency>

<!--easyexcel-->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel</artifactId>
	<version>3.1.1</version>
</dependency>

2、application.yml

常用邮箱SMTP服务器地址大全: 常用邮箱SMTP服务器地址大全-CSDN博客

spring: 
  # 邮箱发送服务配置
  mail:
    host: 
    port: 
    username: 
    password:  # 如果是阿里云邮箱或者Gmail邮箱,填写邮箱密码;否则填写邮箱的授权码
    default-encoding: utf-8
    properties:
      mail:
        # 打印邮件发送过程,生产环境关闭
        debug: true
        smtp:
          connectiontimeout: 5000
          timeout: 3000
          writetimeout: 5000
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory

# commons.mail自定义配置项
email:
  smtp:
    host: 
    email: 
    name: 
    password: 
    port: 

3、配置文件(utils、constant、config一类的)

EmailSpringUtil
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.activation.FileDataSource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.List;

/**
 * @author benjamin_5
 * @Description spring-boot-starter-mail邮件工具类
 * @date 2022/10/5
 */
@Component
@AllArgsConstructor
public class EmailSpringUtil {

	private final JavaMailSender javaMailSender;
	private final MailProperties mailProperties;

	/**
     * 邮件发送
     *
     * @param subject              邮件主题
     * @param content              邮件内容
     * @param contentIsHtml        内容是否为html格式
     * @param fromMailPersonalName 发件人昵称
     * @param toMail               收件人邮箱
     * @param ccMail               抄送人邮箱
     * @param bccMail              秘密抄送人邮箱
     * @param fileNames            文件名(本地路径)
     * @throws GeneralSecurityException
     * @throws UnsupportedEncodingException
     * @throws MessagingException
     */
	public void sendEmail(String subject, String content, boolean contentIsHtml, String fromMailPersonalName,
						  String toMail, String ccMail, String bccMail, List<String> fileNames) throws MessagingException, UnsupportedEncodingException {
		MimeMessage message = javaMailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setFrom(mailProperties.getUsername(), fromMailPersonalName);
		helper.setTo(toMail);
		if (!ObjectUtils.isEmpty(ccMail)) {
			helper.setCc(ccMail);
		}
		if (!ObjectUtils.isEmpty(bccMail)) {
			helper.setBcc(bccMail);
		}
		helper.setSubject(subject);
		helper.setText(content, contentIsHtml);
		// 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
		if (!CollectionUtils.isEmpty(fileNames)) {
			for (String fileName : fileNames) {
				FileDataSource fileDataSource = new FileDataSource(fileName);
				helper.addAttachment(fileDataSource.getName(), fileDataSource);
			}
		}
		javaMailSender.send(message);
	}

	public void sendEmail(String subject, String content, boolean contentIsHtml, String fromMailPersonalName,
						  String toMail, String ccMail, String bccMail, File[] files) throws MessagingException, UnsupportedEncodingException {
		MimeMessage message = javaMailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(mailProperties.getUsername(), fromMailPersonalName);
        helper.setTo(toMail);
        if (!ObjectUtils.isEmpty(ccMail)) {
            helper.setCc(ccMail);
        }
        if (!ObjectUtils.isEmpty(bccMail)) {
            helper.setBcc(bccMail);
        }
        helper.setSubject(subject);
        helper.setText(content, contentIsHtml);
        // 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
        if (!ObjectUtils.isEmpty(files)) {
            for (File file : files) {
                helper.addAttachment(file.getName(), file);
            }
        }
        javaMailSender.send(message);
    }

    public void sendEmail(String subject, String content, boolean contentIsHtml, String fromMailPersonalName,
                          String toMail, String ccMail, String bccMail, String fileName, InputStreamSource fileInput) throws MessagingException, UnsupportedEncodingException {
        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(mailProperties.getUsername(), fromMailPersonalName);
        helper.setTo(toMail);
        if (!ObjectUtils.isEmpty(ccMail)) {
            helper.setCc(ccMail);
        }
        if (!ObjectUtils.isEmpty(bccMail)) {
            helper.setBcc(bccMail);
        }
        helper.setSubject(subject);
        helper.setText(content, contentIsHtml);
        // 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
        if (fileInput != null) {
            helper.addAttachment(fileName, fileInput);
        }
        javaMailSender.send(message);
    }

}

EmailToLongConfig
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @author benjamin_5
 * @Description
 * @date 2022/10/5
 */
@Configuration
public class EmailToLongConfig {

    @PostConstruct
    private void init(){
        // 解决邮件附件名称太长会自动截取,导致附件变成.bin格式问题
        System.setProperty("mail.mime.splitlongparameters","false");
    }

}

SmtpProperties
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author benjamin_5
 * @Description
 * @date 2022/10/5
 */
@Data
@Component
@ConfigurationProperties(value = "email.smtp")
public class SmtpProperties {

    /**
     * smtp服务地址
     */
    private String host;

    /**
     * 发件人邮箱
     */
    private String email;

    /**
     * 发件人昵称
     */
    private String name;

    /**
     * 邮箱授权码
     */
    private String password;

    /**
     * 邮箱服务端口
     */
    private Integer port=25;
}

DataListener
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.util.ConverterUtils;
import lombok.EqualsAndHashCode;

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

/**
 * @author benjamin_5
 * @Description 数据监听类
 * @date 2022/10/5
 */
@EqualsAndHashCode(callSuper = true)
public class DataListener<T> extends AnalysisEventListener<T> {

    /**
     * 缓存数据列表
     */
    private final List<T> dataList = new ArrayList<>();

    @Override
    public void invoke(T data, AnalysisContext context) {
        dataList.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        this.invokeHeadMap(ConverterUtils.convertToStringMap(headMap,context),context);
    }

    public List<T> getDataList() {
        return dataList;
    }

}

EmailCommonsUtil

import com.frame.system.common.easyexcel.config.SmtpProperties;
import lombok.AllArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.UnsupportedEncodingException;

/**
 * @author benjamin_5
 * @Description commons邮件工具类
 * @date 2022/10/3
 */
@AllArgsConstructor
@Component
public class EmailCommonsUtil {
    private static final Log logger = LogFactory.getLog(EmailCommonsUtil.class);

    private final SmtpProperties emailProperties;

    /**
     * 邮件发送
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param contentIsHtml 内容是否为html格式
     * @param toMail 收件人邮箱
     * @param ccMail 抄送人邮箱
     * @param bccMail 秘密抄送人邮箱
     * @param fileList 附件
     */
    public void sendEmail(String subject, String content,boolean contentIsHtml,
                                  String[] toMail, String[] ccMail, String[] bccMail, File[] fileList)
            throws EmailException, UnsupportedEncodingException {
        HtmlEmail email = new HtmlEmail();
        // smtp服务地址
        email.setHostName(emailProperties.getHost());
        // 邮件验证
        email.setAuthentication(emailProperties.getEmail(),emailProperties.getPassword());
        // smtp端口
        email.setSmtpPort(emailProperties.getPort());
        email.setCharset("utf-8");
        // 发件人邮箱地址及昵称
        email.setFrom(emailProperties.getEmail(),emailProperties.getName());
        // 收件人邮箱
        email.addTo(toMail);
        if(!ObjectUtils.isEmpty(ccMail)){
            // 抄送人邮箱
            email.addCc(ccMail);
        }
        if(!ObjectUtils.isEmpty(bccMail)){
            // 秘密抄送人邮箱
            email.addBcc(bccMail);
        }
        // 主题
        email.setSubject(subject);
        if(contentIsHtml){
            email.setHtmlMsg(content);
        }else{
            email.setMsg(content);
        }
        // 设置附件
        if(!ObjectUtils.isEmpty(fileList)){
            for (File file : fileList) {
                EmailAttachment emailAttachment = new EmailAttachment();
                emailAttachment.setName(MimeUtility.encodeText(file.getName()));
                emailAttachment.setPath(file.getPath());
                email.attach(emailAttachment);
            }
        }
        // 发送邮件
        email.send();
        logger.info("邮件发送完成");
    }

}

EmailJavaxUtil

import com.sun.mail.util.MailSSLSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.*;

/**
 * @author benjamin_5
 * @Description javax邮件工具类
 * @date 2022/10/3
 */
public class EmailJavaxUtil {

    private static final Logger logger = LoggerFactory.getLogger(EmailJavaxUtil.class);

    public static void main(String[] args) throws MessagingException, GeneralSecurityException, UnsupportedEncodingException {
        String fileName = "/Library/project/study/java/mail_send_demo/src/main/resources/供应商接口参数.xlsx";
        String html = "<h1>统计数据如下所示:</h1>" +
                "<table border=\"1\">\n" +
                "  <tr>\n" +
                "    <th>月度销售额</th>\n" +
                "    <th>年度销售额</th>\n" +
                "  </tr>\n" +
                "  <tr>\n" +
                "    <td>10000</td>\n" +
                "    <td>2000000</td>\n" +
                "  </tr>\n" +
                "</table>";
        sendEmail("统计数据",html,true,"55555","wuhanxue5@sina.com",null,null, Collections.singletonList(fileName));
    }

    private static final String senderSmtpHost = "smtp.qq.com";
    private static final String senderEmail = "xxx@qq.com";
    private static final String senderPassword = "xxx";
    private static final String senderSmtpPort = "465";

    /**
     * 邮件发送
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param contentIsHtml 内容是否为html格式
     * @param fromMailPersonalName 发件人昵称
     * @param toMail 收件人邮箱
     * @param ccMail 抄送人邮箱
     * @param bccMail 秘密抄送人邮箱
     * @param fileNames 文件名(本地路径)
     * @throws GeneralSecurityException
     * @throws UnsupportedEncodingException
     * @throws MessagingException
     */
    private static void sendEmail(String subject, String content,boolean contentIsHtml, String fromMailPersonalName,
                                  String toMail, String ccMail, String bccMail, List<String> fileNames)
            throws GeneralSecurityException, UnsupportedEncodingException, MessagingException {

        // 设置参数
        Properties properties = System.getProperties();
        // smtp服务地址
        properties.put("mail.smtp.host",senderSmtpHost);
        // smtp服务端口
        properties.put("mail.smtp.port", senderSmtpPort);
        // 开启验证
        properties.put("mail.smtp.auth","true");
        // 开启TLS加密
        properties.put("mail.smtp.starttls.enable","true");
        // 是否启用socketFactory,默认为true
        properties.put("mail.smtp.socketFactory.fallback", "true");
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");
        properties.put("mail.smtp.ssl.socketFactory", sf);
        // 建立会话,利用内部类将邮箱授权给jvm
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(senderEmail, senderPassword);
            }
        });
        // 设置为true可以在控制台打印发送过程,生产环境关闭
        session.setDebug(true);
        // 创建邮件对象
        MimeMessage message = new MimeMessage(session);
        // 通过MimeMessageHelper设置正文和附件,否则会导致两者显示不全
        MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");
        //设置收件人,to为收件人,cc为抄送,bcc为密送
        if (StringUtils.isEmpty(toMail)) {
            logger.error("邮件收件人为空");
            return;
        }
        //设置发件人
        helper.setFrom(new InternetAddress(senderEmail, fromMailPersonalName));
        helper.setTo(InternetAddress.parse(toMail, false));
        if (!StringUtils.isEmpty(ccMail)) {
            helper.setCc(InternetAddress.parse(ccMail, false));
        }
        if (!StringUtils.isEmpty(bccMail)) {
            helper.setBcc(InternetAddress.parse(bccMail, false));
        }
        // 设置邮件主题
        helper.setSubject(subject);
        //设置邮件正文内容
        helper.setText(content,contentIsHtml);
        //设置发送的日期
        helper.setSentDate(new Date());
        // 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
        if(!CollectionUtils.isEmpty(fileNames)){
            for (String fileName : fileNames) {
                FileDataSource fileDataSource = new FileDataSource(fileName);
                helper.addAttachment(fileDataSource.getName(),fileDataSource);
            }
        }
        //调用Transport的send方法去发送邮件
        Transport.send(message);
    }
}

ExcelUtil
import com.alibaba.excel.EasyExcel;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @author benjamin_5
 * @Description
 * @date 2022/10/5
 */
public class ExcelUtil {

    /**
     * 生成excel文件
     * @param fileName excel文件路径
     * @param dataList 数据列表
     * @param clazz 导出对象类
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> File generateExcel(String fileName, List<T> dataList, Class<T> clazz) throws IOException {
        // 生成文件
        File excel = new File(fileName);
        // excel写入
        EasyExcel.write(excel,clazz).sheet(0).doWrite(dataList);
        return excel;
    }

    public static <T> ByteArrayOutputStream generateExcel(List<T> dataList, Class<T> clazz) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // excel写入
        EasyExcel.write(out,clazz).sheet(0).doWrite(dataList);
        return out;
    }
}

4、EmailCodeService

import com.frame.system.common.easyexcel.utils.EmailSpringUtil;
import com.frame.system.common.easyexcel.utils.ExcelUtil;
import com.frame.system.common.enums.ServiceErrorEnum;
import com.frame.system.common.exception.ServiceException;
import com.frame.system.controller.response.RechargeData;
import com.frame.system.domain.BuyerUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class EmailCodeService {

    // 这个是 mail 依赖提供给我们的发送邮件的接口
    @Autowired
    private JavaMailSender mailSender;

    // 获取发件人邮箱
    @Value("${spring.mail.username}")
    private String sender;

    @Value("${email.smtp.name}")
    private String mailPersonalName;

    @Autowired
    private EmailSpringUtil emailSpringUtil;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public static boolean isValidEmail(String username) {
        // 邮箱的正则表达式
        String emailRegex = "^[a-z0-9]+(\\.[a-z0-9]+)*@[a-z0-9]+(\\.[a-z0-9]+)*(\\.[a-z]{2,})$";
        return username.matches(emailRegex) && username.length() >= 6;
    }

    public void sendCode(String email) {
        // 转为小写
        String lowerCase = email.toLowerCase();
        if (!isValidEmail(lowerCase)) {
            throw new ServiceException(ServiceErrorEnum.EMAIL_ERROR);
        }
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom('<' + sender + '>');
        message.setTo(email);
        message.setSubject("欢迎访问美团医药系统");
        String s = runNumber();
        String content = "【验证码】您的验证码为:" + s + " 。 验证码三分钟内有效,逾期作废。";
        message.setText(content);
        mailSender.send(message);
        log.info("[发送短信] 发送成功,邮箱号:{},发送内容:{}", email, s);
        redisTemplate.opsForValue().set("client:code:" + email, s, 1, TimeUnit.MINUTES);
    }

    //    生成随机的验证码
    public static String runNumber() {
        String str = "0123456789";
        StringBuilder sb = new StringBuilder(6);
        for (int i = 0; i < 6; i++) {
            char ch = str.charAt(new Random().nextInt(str.length()));
            sb.append(ch);
        }
        return sb.toString();
    }

    public void checkCode(String email, String code) {
        String sysCode = (String) redisTemplate.opsForValue().get("client:code:" + email);
        Assert.notNull(sysCode, "验证码错误或已过期");
        Assert.isTrue(Objects.equals(code, sysCode), "验证码错误");
        redisTemplate.delete("client:code:" + email);
    }

    public void sendEmailByTemplate(List<RechargeData> dataList, BuyerUser buyerUser) {
        // 获取资源文件存放路径,用于临时存放生成的excel文件
        String path = this.getPath();
        // 文件名:采用UUID,防止多线程同时生成导致的文件重名
        String fileName = String.format("%s充值明细表数据-%s.xlsx", path, UUID.randomUUID());
        try {
            // 生成excel文件
            File excel = ExcelUtil.generateExcel(fileName, dataList, RechargeData.class);
            // 发送邮件
            String content = "";
            String toMail = buyerUser.getEmail();
            String ccMail = sender;
            emailSpringUtil.sendEmail("s充值明细表数据", content, true, mailPersonalName,
                    toMail, ccMail, null, Collections.singletonList(fileName));
            // 邮件发送完成后删除临时生成的excel文件
            excel.delete();
        } catch (IOException e) {
            log.error(String.format("生成excel失败,原因:%s", e));
            e.printStackTrace();
        } catch (MessagingException e) {
            log.error(String.format("邮件发送失败,原因:%s", e));
            e.printStackTrace();
        } catch (javax.mail.MessagingException e) {
            throw new RuntimeException(e);
        }
    }

    private String getPath() {
        // 添加资源文件夹中的相对路径到最终的路径,这里使用的服务器的路径
        return "/www/wwwroot/meituan-h5.test.muke.design/excel/";
    }
}

5、controller层代码

此处仅为举例,核心代码为第8行和第9行。

@GetMapping("/generateExcelAndSend")
@ApiOperation("发送附件")
public Result<?> generateExcelAndSend(@RequestParam Long userId,
                                      @RequestParam(required = false) String startTime) {
    buyerUserService.checkUserContains(userId);
    BuyerUser buyerUser = buyerUserService.getById(userId);
    buyerUserService.checkEmailContains(buyerUser);
    List<RechargeData> dataList = buyerOrderService.selectRechargeExcelOrderList(userId, startTime);
    emailCodeService.sendEmailByTemplate(dataList, buyerUser);
    return Result.success();
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以提供一些基本的步骤: 1. 在Java中使用Apache POI库创建Excel文件 2. 使用JavaMail API连接邮箱服务器并创建邮件 3. 将Excel文件作为附件添加到邮件中 4. 设置邮件主题、内容、接收人等信息 5. 发送邮件 以下是一些参考代码: ```java // 1. 创建Excel文件 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); Row row = sheet.createRow(0); row.createCell(0).setCellValue("Hello"); row.createCell(1).setCellValue("World"); FileOutputStream outputStream = new FileOutputStream("example.xlsx"); workbook.write(outputStream); outputStream.close(); // 2. 创建邮件 Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.host", "smtp.gmail.com"); // 邮箱服务器 props.put("mail.smtp.port", "587"); // 邮箱SMTP端口 Session session = Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("your-email-address", "your-email-password"); } }); Message message = new MimeMessage(session); message.setFrom(new InternetAddress("your-email-address")); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient-email-address")); message.setSubject("Test Email"); // 3. 添加附件 MimeBodyPart attachmentPart = new MimeBodyPart(); attachmentPart.attachFile(new File("example.xlsx")); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(attachmentPart); // 4. 设置邮件内容、附件等信息 MimeBodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setContent("This is a test message", "text/html"); multipart.addBodyPart(messageBodyPart); message.setContent(multipart); // 5. 发送邮件 Transport.send(message); ``` 提醒一下,以上示例代码仅供参考,需要自己根据具体情况进行适当的修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值