• springboot添加邮件发送及压缩功能


    springboot添加邮件发送及文件压缩功能

    转载请注明出处https://www.cnblogs.com/funnyzpc/p/9190233.html

      先来一段诗

    ```

      就这样吧

      忍受折磨

      然后,躺进医院

      然后,死去

      化作一抔土

      从此,这世界没有烦恼

      没有病痛

      没有我

      也没有这个世界

    ```

      以上是在半睡半醒中想到的,写的不好,读者可直接略过。

      这次本来只讲讲邮件发送功能的,惮于内容比较贫乏,故加了点儿文件压缩的功能讲解。

      首先邮件发送,邮件功能在springboot里面是有对应的依赖组件,这个:

    1 <dependency>
    2     <groupId>org.springframework.boot</groupId>
    3     <artifactId>spring-boot-starter-mail</artifactId>
    4 </dependency>

    邮件功能开发在springboot里面相当简单,这里我大致总结下开发内容:

        A>添加依赖包

        B>配置Mail基本参数(ymal或propertie里面)

        C>Service中注入JavaMailSender,调用相关方法即可

    但是这里面可能会有个问题,就是在具体服务器部署的时候服务器会封堵邮件服务端口,以及普通邮件安全问题,这里讲解的时候我会顺道给出解决之道。

      首先,需要在工程的pom.xml中引入邮件组件,组件的版本需对应springboot的版本(可不写,这里我略去):

    1  <dependency>
    2      <groupId>org.springframework.boot</groupId>
    3      <artifactId>spring-boot-starter-mail</artifactId>
    4  </dependency>

      

      接下来就是在配置文件中配置邮件的基本参数:

     1 spring:
     2     mail:
     3       host: smtp.exmail.qq.com
     4       username: username@hostname.com
     5       password: 密码
     6       default-encoding: UTF-8
     7       ssl:
     8         trust: smtp.exmail.qq.com
     9       properties:
    10         mail:
    11           smtp:
    12             auth: true  #是否需要认证
    13             socketFactory:
    14               class: javax.net.ssl.SSLSocketFactory #SSL证书Socket工厂
    15               port: 465 #使用SMTP465端口

      

    配置参数的时候一定要注意缩进,因为我给的是yaml的配置格式,若是properties配置,大致是这样子(例子):spring.mail.host:smtp.exmail.qq.com,每一个子项都是完整的格式,一开始我是省略了properties项以下的配置(是否认真,SSL,端口),后来发现服务器将邮件的25端口封了,所以在本地可以但是在服务器就行不通了,所以需要指定邮件服务端口为465,我这里使用的是qq邮箱,如果使用163或其他邮箱需自行查阅服务商支持的端口,至于邮件安全问题,在这里需要声明两个,一个是ssl信任,以及mail的socket工厂,具体请见以上红色部分,以上配置仅对qq邮箱有效,不保证其他邮箱也适用。

      ok,配置完成,这里就开始写具体的实现类:

      1 import XXX.common.util.DateUtil;
      2 import org.apache.commons.lang3.StringUtils;
      3 import org.slf4j.Logger;
      4 import org.slf4j.LoggerFactory;
      5 import org.springframework.beans.factory.annotation.Autowired;
      6 import org.springframework.beans.factory.annotation.Value;
      7 import org.springframework.mail.SimpleMailMessage;
      8 import org.springframework.mail.javamail.JavaMailSender;
      9 import org.springframework.mail.javamail.MimeMessageHelper;
     10 import org.springframework.stereotype.Service;
     11 
     12 import javax.mail.internet.MimeMessage;
     13 import java.util.Date;
     14 import java.util.List;
     15 import java.util.Map;
     16 
     17 @Service
     18 public class MailService {
     19     private static final Logger LOG = LoggerFactory.getLogger(MailService.class);
     20 
     21     @Value("${spring.mail.username}")
     22     private String SEND_USER_ADDR;
     23 
     24     @Autowired
     25     private JavaMailSender mailSender;
     26 
     27     /**
     28      *      发送简单邮件
     29      * @param receive   收件人
     30      * @param obj       发送主题
     31      * @param content   邮件内容
     32      */
     33     public void sendSimpleMail(String receive,String obj,String content) {
     34         if(!StringUtils.isNotBlank(content) || !StringUtils.isNotBlank(receive))
     35             return;//不发送空邮件
     36         SimpleMailMessage message = new SimpleMailMessage();
     37         message.setFrom(SEND_USER_ADDR);
     38         if(receive.contains(";"))
     39             message.setTo(receive.split(";"));
     40         else
     41             message.setTo(receive);
     42         message.setSubject(obj);
     43         message.setText(content);
     44         try {
     45             mailSender.send(message);
     46             LOG.info("Simple mail send success!");
     47         } catch (Exception e) {
     48             LOG.error("sendSimpleMail ERROR!", e);
     49         }
     50 
     51     }
     52 
     53     private StringBuilder strBuilder;
     54     /**
     55      *  发送html邮件 多列表单的形式
     56      * @param receive   收件人
     57      * @param obj       发送主题(题目)
     58      * @param content   邮件内容
     59      */
     60     public void sendHtmlMailByList(String receive,String obj,List<Map> content){
     61             if(content.isEmpty() || !StringUtils.isNotBlank(receive) || null==obj)
     62                 return;
     63             MimeMessage msg = mailSender.createMimeMessage();
     64             try {
     65                 MimeMessageHelper helper = new MimeMessageHelper(msg, true, "UTF-8"); //解决乱码问题
     66                 helper.setFrom(SEND_USER_ADDR);
     67                 if(receive.contains(";"))
     68                     helper.setTo(receive.split(";"));
     69                 else
     70                     helper.setTo(receive);
     71                 helper.setSubject(obj);
     72                 strBuilder=new StringBuilder();
     73                 strBuilder.append("<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="padding:3% 2%;">");
     74                 strBuilder.append("<h2>This message is automatically sent to the system.</h2>");
     75                 strBuilder.append("<h2>Send Date by "+DateUtil.getDateFormat(new Date(),DateUtil.DATETIME_DEFAULT_FORMAT) +"</h2>");
     76                 strBuilder.append("<h2>The following is the details:</h2>");
     77                 strBuilder.append("<table border="2px solid red" width="100%">");
     78 
     79                 //
     80                 strBuilder.append("<thead style="background-color: #aea2e2;">");
     81                 strBuilder.append("<tr>");
     82                 Object[] st=content.get(0).keySet().toArray();
     83                 for(int i=0;i<st.length;i++)
     84                     strBuilder.append("<th>"+st[i]+"</th>");
     85                 strBuilder.append("</tr>");
     86                 strBuilder.append("</thead>");
     87 
     88                 //
     89                 strBuilder.append("<tbody>");
     90                 for(Map item:content){
     91                     strBuilder.append("<tr>");
     92                     for(Object str:st)
     93                         strBuilder.append("<td>"+item.get(str)+"</td>");
     94                     strBuilder.append("</tr>");
     95                 }
     96                 strBuilder.append("</tbody>");
     97 
     98                 strBuilder.append("</table>");
     99                 strBuilder.append("<h3 style="text-align:right">Best wishes</h3>");
    100                 strBuilder.append("</body></html>");
    101                 //LOG.info(strBuilder.toString());
    102                 helper.setText(strBuilder.toString(),true);
    103             }catch (Exception e){
    104                 LOG.error("sendHtmlMail ERROR:",e);
    105             }
    106             mailSender.send(msg);
    107         }
    108 
    109 
    110     /**
    111      *  发送html邮件 单列记录形式
    112      * @param receive   收件人
    113      * @param obj       发送主题(题目)
    114      * @param content   邮件内容
    115      */
    116     public void sendHtmlMailByItem(String receive,String obj,List<String> content){
    117         if(content.isEmpty() || !StringUtils.isNotBlank(receive) || null==obj)
    118             return;
    119         MimeMessage msg = mailSender.createMimeMessage();
    120         try {
    121             MimeMessageHelper helper = new MimeMessageHelper(msg, true, "UTF-8"); //解决乱码问题
    122             helper.setFrom(SEND_USER_ADDR);
    123             if(receive.contains(";"))
    124                 helper.setTo(receive.split(";"));
    125             else
    126                 helper.setTo(receive);
    127             helper.setSubject(obj);
    128             strBuilder=new StringBuilder();
    129             strBuilder.append("<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="padding:3% 2%;">");
    130             strBuilder.append("<h3>This message is automatically sent to the system.</h3>");
    131             strBuilder.append("<h3>Send Date by "+DateUtil.getDateFormat(new Date(),DateUtil.DATETIME_DEFAULT_FORMAT) +"</h3>");
    132             strBuilder.append("<h3>The following is the details:</h3>");
    133             strBuilder.append("<table border="2px solid red" width="100%">");
    134 
    135             //
    136             strBuilder.append("<thead style="background-color: #aea2e2;">");
    137 
    138             strBuilder.append("<th>"+obj.toUpperCase()+" DETAIL</th>");
    139             strBuilder.append("</thead>");
    140 
    141             //
    142             strBuilder.append("<tbody>");
    143             for(String item:content){
    144                 strBuilder.append("<tr><td>"+item+"</td></tr>");
    145             }
    146             strBuilder.append("</tbody>");
    147 
    148             strBuilder.append("</table>");
    149             strBuilder.append("<h3 style="text-align:right;font-weight:normal;">Best wishes</h3>");
    150             strBuilder.append("</body></html>");
    151             LOG.info(strBuilder.toString());
    152             helper.setText(strBuilder.toString(),true);
    153         }catch (Exception e){
    154             LOG.error("sendHtmlMail ERROR:",e);
    155         }
    156         mailSender.send(msg);
    157     }
    158 }

    以上我是将邮件功能封装成一个服务类,使用的时候只需要将当前类注入 然后直接调用即可,以上封装了两个方法:一个是简单邮件发送,一个是带html table的邮件,如果需要发送附件,需将附件放入到MimeMessageHelper里面(调用addAttachment("文件名", 文件))方法即可,这里因为无实际需求,遂就略去了,好了,邮件发送功能已经完成,这里看下实际效果:

    邮件功能实现完毕,现在我讲讲文件压缩功能,压缩功能的实现大致有四种,分别是:

      A>利用java.util.zip提供的api压缩

      B>利用apache的ant包提供的api压缩(org.apache.tools.ant.taskdefs.Zip)

      C>使用zip4j提供的api压缩(net.lingala.zip4j)

      D>调用宿主机的shell命令压缩

    这里需要特别提到三个问题:

      A>普通邮件压缩中文乱码(不支持中文)

      B>压缩后无法解压(解压错误)

      C>文件压缩添加压缩密码问题

    实际开发过压缩功能,以上三点儿对于新手来说尤其的头痛,这里我分享下以前在开发压缩功能中碰到的问题。

      使用原生java.util包提供的压缩,如果被压缩文件使用到中文,则会乱码(据说是jdk的一个bug),而且压缩实现的代码较为复杂(尤其是设置密码),尤其是对于跨目录压缩和多文件压缩尤其麻烦。

      使用apache提供的zip工具虽避免了以上会出现的问题,但是需要提醒一点儿的是这个ant包与webLogic冲突(部署的时候会报错)且无法实现压缩设置密码,如果使用的是webLogic而不是tomocat的情况下,一定要注意到这个问题。

      使用java调用宿主机的shell命令也是个不错的选择,但是,需要编写shell命令,同时对于部署在windows平台就不太友好了,移植比较麻烦

      最后,对于以上问题,我这里推荐zip4j,以下也是针对zip4j的压缩实现做讲解。

      先,需要引入依赖包

    1       <!--压缩:支持加密压缩-->
    2         <dependency>
    3             <groupId>net.lingala.zip4j</groupId>
    4             <artifactId>zip4j</artifactId>
    5             <version>1.3.2</version>
    6         </dependency>

      再,封装一个压缩/解压缩工具类以方便使用

     1 import net.lingala.zip4j.core.ZipFile;
     2 import net.lingala.zip4j.exception.ZipException;
     3 import net.lingala.zip4j.model.ZipParameters;
     4 import net.lingala.zip4j.util.Zip4jConstants;
     5 import org.springframework.util.StringUtils;
     6 
     7 import java.io.File;
     8 
     9 
    10 /**
    11  * 本工具类使用Zip4j来进行压缩以及解压缩
    12  */
    13 public class ZipUtil {
    14 
    15     //声明压缩对象
    16     private static ZipParameters parameters;
    17 
    18     //解压文件对象
    19     private static ZipFile zipFile;
    20 
    21     /**
    22      *
    23      * @param sourceFilePath    被压缩的文件的路径(单文件,文件夹)
    24      * @param zipFilePath       压缩文件路径
    25      * @param password          压缩密码
    26      * @return                  压缩成功:true ,压缩失败:false
    27      */
    28     public static Boolean singleFileCompress(String sourceFilePath,String zipFilePath,String password){
    29         parameters = new ZipParameters();
    30         parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 压缩方式(默认方式)
    31         parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); // 压缩级别(默认级别)
    32         //压缩加密设置
    33         if (!StringUtils.isEmpty(password)) {
    34             parameters.setEncryptFiles(true);//是否设置文件加密(默认为否)
    35             parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); // 加密方式(此处是标准压缩)
    36             parameters.setPassword(password.toCharArray());
    37         }
    38         try {
    39             ZipFile zipFile = new ZipFile(zipFilePath);
    40             //如果是文件则直接压缩,若是文件夹,遍历文件全部压缩
    41             if(new File(sourceFilePath).isFile()) {
    42                 zipFile.setFileNameCharset("GBK");
    43                 zipFile.addFile(new File(sourceFilePath), parameters);
    44                 return true;
    45             }
    46             //File ff=new File(sourceFilePath);
    47             File[] flst=new File(sourceFilePath).listFiles();
    48             System.out.println("文件个数=>"+flst.length);
    49             for(File f:flst){
    50                 zipFile.setFileNameCharset("GBK");
    51                 zipFile.addFile(f, parameters);
    52             }
    53 
    54             return true;
    55         } catch (ZipException e) {
    56             e.printStackTrace();
    57             return false;
    58         }catch (Exception id){
    59             id.printStackTrace();
    60             return false;
    61         }
    62     }
    63     public static Boolean unZip(String zipFile,String unZipDir){
    64         try {
    65             ZipUtil.zipFile = new ZipFile(zipFile);
    66             ZipUtil.zipFile.setFileNameCharset("GBK");//设置编码格式
    67             //用自带的方法检测一下zip文件是否合法,包括文件是否存在、是否为zip文件、是否被损坏等
    68             if (!ZipUtil.zipFile.isValidZipFile()) {
    69                 throw new ZipException("文件不合法或不存在");
    70             }
    71             // 跟java自带相比,这里文件路径会自动生成,不用判断
    72             ZipUtil.zipFile.extractAll(unZipDir);
    73             return true;
    74         }catch(ZipException e){
    75             return false;
    76         }
    77     }
    78

    以上压缩方法自带密码压缩功能,可以压缩单文件也可以压缩目录文件,相对于原生的实现,一下子清爽了许多,这里唯一需要说明的是,压缩的目标文件在压缩前一定不能穿件,否则会报错!另外对于解压缩一定要注意文件编码和判断文件是否存在。

      OK,本章的功能已尽数分享,希望各位在开发功能的时候能避免这其中的

      现在是2018-07-14 22:16:12 ,各位晚安

  • 相关阅读:
    初识数据库与SQL语句
    初始面向对象
    集合与深浅copy
    函数进阶
    函数操作
    文件操作
    生成器与列表生成式
    函数名的本质,闭包和迭代
    小数据库
    DAY 5 字典
  • 原文地址:https://www.cnblogs.com/funnyzpc/p/9190233.html
Copyright © 2020-2023  润新知