npm 包解析 eml 文件

背景

后台问我能不能前端直接解析 eml 文件,项目是 Vue , 首先想到能不能 npm 找个包解析


过程

  1. 首先上 npmjs 直接搜 eml , 找到了一个 eml-format
  2. 了解 quoted-printable 编码,随后发现我从QQ邮箱导出的 eml 文件是 GB2312 编码,因为之前对编码不熟悉, JS 也没有直接对它解码的方法,想用 JS 原生的编解码方法也没弄好
  3. 最后找到一个 js对中文进行gb2312/gbk编码解码 , 确定从里面下载的 js 文件确实可以解码 GB2312 编码,于是稍作修改之后放到项目中引用,解析如下:

    
    // 这里的 attachments 是我直接用 eml-format  对字符串解析得到的对象里获取到的内容属性
    // 但是使用请求工具, 如 axios , 其get方法直接获取服务器上的 eml 文件,返回的字符串保险起见再 .toString() 一下,再用 eml-format 解析,这时格式会发生变化,内容属性不一定是 attachments , 甚至不一定是数组, 具体情况具体分析
    temp.attachments.map(item => {
         let tempData = item.data;
         tempData = tempData.slice(tempData.indexOf('Transfer-Encoding: quoted-printable') + 'Transfer-Encoding: quoted-printable'.length); // 去掉多余数据
         tempData = tempData.replace(/=\r\n/g, ''); // 去除 quoted-printable 行末等号,以免影响汉字匹配
         let reg = /((=[0-9|A-F]{2}){2})/g; // GB2312 汉字检测,连续两个 '=xx' 才能解析为一个汉字
         tempData = tempData.replace(reg, function (str, a) {
             return gbDecode.decode(a.replace(/=/g, '%'));
         }); // 转换汉字
         tempData = tempData.replace(/(=[0-9|A-F]{2})/g, function (str, a) {
             return gbDecode.decode(a.replace(/=/g, '%'));
         }); // 转换符号(剩余的单个 '=xx')
         item.data = tempData;
    });
  4. 但是之后我在搜索 GB2312 时发现了一个更好的包, emailjs-mime-codec ,于是新的解析代码如下:

    
    // 引入
    import * as emlFormat from 'eml-format';
    import * as Codec from 'emailjs-mime-codec';
    
    // 项目里用的 axios ,这里就跟着用了
    // this.emlData 是 vue 的用法, 用它之前我已在 vue 定义了这个变量
    axios.get('服务器请求url').then(response => {
       this.emlData = response.data.toString(); // 不 .toString() 可能有些稀奇古怪的问题
       this.emlData = this.emlData.replace(/(=\?[\s\S]*?\?=)/g, function (str, a) { // 正则替换一些地方(目前只发现了 subject 邮件主题是这样)的 =?...?= 
           return escape(Codec.mimeWordsDecode(a)); // 返回解码后又被 escape 编码的字符串,另外大家都说 escape 弃用了,那看要不要换成 encodeURI 吧  
       });
    });
    
    // 这个 parsedEmlData 是在 vue 的 computed 定义的计算属性,可以根据 this.emlData 的变化而动态调用 下面的 getter 函数,函数返回新值
    parsedEmlData: function () {
        let temp = this.emlData;
        temp = Codec.quotedPrintableDecode(temp, 'GB2312'); // 整体解码,替换原来的手动正则匹配
        let returnValue = {};
        emlFormat.read(temp, (err, data) => {
            if (err) {
                console.log(err);
            } else {
                data.subject = unescape(data.subject); // 把之前的 escape 编码的数据解码回中文,不走这一步整体解码后这里很可能不会被解码,还有些其他原因,有兴趣的可以试试,同理,之前用 encodeURI 的话这里就用 decodeURI
                returnValue = data;
            }
        });
        return returnValue;
    }
    

后续

后台说这个只是储备,他们有接口可以返回后台解析的数据……


其他

escape,encodeURI,encodeURIComponent有什么区别? - 水乙的回答 - 知乎

猜你喜欢

转载自blog.csdn.net/u013836242/article/details/80372428