mime 邮件内容解析

因为需要解析apache james的邮件内容 ,内容格式如下

Return-Path: <XXXX@163.com>
Delivered-To: ***@**
Received: from m13-61.163.com (EHLO m13-61.163.com) ([220.181.13.61])
          by VM_0_5_centos (JAMES SMTP Server ) with ESMTP ID -1461210387
          for <XXXX@lawback.net>;
          Fri, 14 Dec 2018 15:35:46 +0800 (CST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com;
	s=s110527; h=Date:From:Subject:MIME-Version:Message-ID; bh=LGN55
	QdgU9XoPQCr+27/Z+IPGOdDWiYZ7swbWaIAMzM=; b=P3wXeY5gFeuR5YVOBMga4
	OHrnfwD+rYOKLUpTuaupgr/d/JftXBkufTMp8tIloy1njIPwt4Vp7oiJHAGT1gSi
	k48Fk7CP30e6E8pXk4+LUfVaOinunqbdGgVzkmtkZnZu4U4X/vhRIxNLICB8kTSu
	khVfkoXrWroSS2Q6HHAwpQ=
Received: from XXXX$163.com ( [59.83.198.133] ) by
 ajax-webmail-wmsvr61 (Coremail) ; Fri, 14 Dec 2018 15:35:45 +0800 (CST)
X-Originating-IP: [59.83.198.133]
Date: Fri, 14 Dec 2018 15:35:45 +0800 (CST)
From: 1 <hy1131468749@163.com>
To: "hanyu@lawback.net" <hanyu@lawback.net>
Subject: kjchjkch
X-Priority: 3
X-Mailer: Coremail Webmail Server Version SP_ntes V3.5 build
 20160729(86883.8884) Copyright (c) 2002-2018 www.mailtech.cn 163com
X-CM-CTRLDATA: xShnzGZvb3Rlcl9odG09MTAwOjU2
Content-Type: multipart/mixed; 
	boundary="----=_Part_183728_654166346.1544772945612"
MIME-Version: 1.0
Message-ID: <4414f0b3.bd9f.167aba486cd.Coremail.hy1131468749@163.com>
X-Coremail-Locale: zh_CN
X-CM-TRANSID:PcGowACHOSlRXRNcmW4QAA--.464W
X-CM-SenderInfo: 1k1rijqruwmliuz6il2tof0z/1tbiDwUdOVUMJg-i4gACsc
X-Coremail-Antispam: 1U5529EdanIXcx71UUUUU7vcSsGvfC2KfnxnUU==

------=_Part_183728_654166346.1544772945612
Content-Type: multipart/alternative; 
	boundary="----=_Part_183730_484598546.1544772945613"

------=_Part_183730_484598546.1544772945613
Content-Type: text/plain; charset=GBK
Content-Transfer-Encoding: base64

c2tkaGFza2pkaDG72ODB1/fPsrPJuaYx
------=_Part_183730_484598546.1544772945613
Content-Type: text/html; charset=GBK
Content-Transfer-Encoding: base64

PGRpdiBzdHlsZT0ibGluZS1oZWlnaHQ6MS43O2NvbG9yOiMwMDAwMDA7Zm9udC1zaXplOjE0cHg7
Zm9udC1mYW1pbHk6QXJpYWwiPnNrZGhhc2tqZGgxu9jgwdf3z7KzybmmMTwvZGl2Pjxicj48YnI+
PHNwYW4gdGl0bGU9Im5ldGVhc2Vmb290ZXIiPjxwPiZuYnNwOzwvcD48L3NwYW4+
------=_Part_183730_484598546.1544772945613--

------=_Part_183728_654166346.1544772945612
Content-Type: text/plain; name="=?GBK?Q?=B2=E2=CA=D422.txt?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="=?GBK?Q?=B2=E2=CA=D422.txt?="

vM6088/Dv9W85Lu5yse087/Nu6e94r72DQo=
------=_Part_183728_654166346.1544772945612--

一个完成邮箱格式内容在apache jame里包括头信息和 内容信息

 

先从数据库取出这2个信息进行相加。

然后在pom文件需要加入以下jar:

<dependency>
                <groupId>org.apache.james</groupId>
                <artifactId>apache-mime4j-core</artifactId>
                <version>${mime4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.james</groupId>
            <artifactId>apache-mime4j-dom</artifactId>
            <version>${mime4j.version}</version>
        </dependency>

代码如下:

public class JamesUtil {
    /**
     * 获取邮件内容
     * @param mailBoxId mailBoxId
     * @param mailUid mailUid
     * @return Map<String, Object>
     */
    public static Map<String, Object> getMailContent(String mailBoxId,String mailUid){

        if(StringUtils.isEmpty(mailBoxId) || StringUtils.isEmpty(mailUid)){
            return null;
        }
        IJamesMailService jamesMailService = SpringContextUtils.getBean(IJamesMailService.class);
        JamesMail jamesMail = jamesMailService.selectByBoxIdAndUid(mailBoxId, mailUid);
        if(jamesMail == null){
            return null;
        }
        Map<String,Object> resultMap = new HashMap<>();
        ByteArrayInputStream inputStringStream = null;
        try {
            String head = new String(jamesMail.getHeaderBytes());
            String content =new String(jamesMail.getMailBytes());
            inputStringStream = new ByteArrayInputStream((head + content).getBytes());
//apache 提供的邮件mime格式解析
            MimeTokenStream parser = new MimeTokenStream(MimeConfig.PERMISSIVE, new DefaultBodyDescriptorBuilder());
            parser.parse(inputStringStream);
            handle(parser, resultMap);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(inputStringStream != null) {
                try {
                    inputStringStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return resultMap;

    }

    private static void handle(MimeTokenStream parser,Map<String,Object> resultMap) throws Exception {
        for (EntityState state = parser.getState();
             state != EntityState.T_END_OF_STREAM;
             state = parser.next()) {
            switch (state) {
//到了这个状态,会获取到之前的头信息,然后获取到流,根据之前的头信息对流进行处理
                case T_BODY:
                    MaximalBodyDescriptor descriptor = (MaximalBodyDescriptor) parser.getBodyDescriptor();
                    LimitedInputStream line = (LimitedInputStream) parser.getInputStream();
                    StringBuilder sb = new StringBuilder();
                    byte[] buffer = new byte[1024 * 4];
                    int n ;
                    while ((n = line.read(buffer)) != -1) {
                        sb.append(new String(buffer, 0, n));
                    }
                    String fileName = descriptor.getContentDispositionFilename();
                    String transferEncoding = descriptor.getTransferEncoding();
                    //处理文件
                    if (!StringUtils.isEmpty(fileName)) {
                        //获取文件名称
                        String fileRealName = MimeUtility.decodeText(fileName);
                        System.out.println(fileRealName);
                        String path = "E:\\" + fileRealName;
                        FileOutputStream fileOutputStream = null;
                        try {
                            File file = new File(path);
                            BASE64Decoder base64Decoder = new BASE64Decoder();
                            byte[] bytes = base64Decoder.decodeBuffer(sb.toString());
                            fileOutputStream = new FileOutputStream(file);
                            fileOutputStream.write(bytes);
                            fileOutputStream.flush();
                            resultMap.put("file",path);
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            if(fileOutputStream != null) {
                                fileOutputStream.close();
                            }
                        }

                    } else {
                        //处理文本内容
                        String contentShow = sb.toString();
                        if (StringUtils.isNotEmpty(transferEncoding)) {
                            String charset = descriptor.getCharset();
                            if ("base64".equals(transferEncoding)) {
                                BASE64Decoder base64Decoder = new BASE64Decoder();
                                byte[] bytes = base64Decoder.decodeBuffer(sb.toString());
                                contentShow = new String(bytes, charset);
                            } else if ("quoted-printable".equals(transferEncoding)) {
                                contentShow = qpDecoding(sb.toString(), charset);
                            }
                        }
                      //  System.out.println("内容:" + contentShow);
                        String subType = descriptor.getSubType();
                        if("html".equals(subType)){
                            resultMap.put("html",contentShow);
                        }else{
                            resultMap.put("text",contentShow);
                        }
                    }
                    break;
                case T_FIELD:
                    break;
                case T_END_MULTIPART:
                    break;
            }
        }

    }




    public static String qpEncodeing(String str,String charset) {
        if(StringUtils.isEmpty(str)){
            return "";
        }
        char[] encode = str.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < encode.length; i++)
        {
            if ((encode[i] >= '!') && (encode[i] <= '~') && (encode[i] != '=')
                    && (encode[i] != '\n'))
            {
                sb.append(encode[i]);
            }
            else if (encode[i] == '=')
            {
                sb.append("=3D");
            }
            else if (encode[i] == '\n')
            {
                sb.append("\n");
            }
            else
            {
                StringBuilder sbother = new StringBuilder();
                sbother.append(encode[i]);
                String ss = sbother.toString();
                byte[] buf = null;
                try
                {
                    buf = ss.getBytes(charset);
                }
                catch (UnsupportedEncodingException e)
                {
                    e.printStackTrace();
                }
                if(buf == null){
                    continue;
                }
                if (buf.length == 3)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        String s16 = String.valueOf(Integer.toHexString(buf[j]));
                        // 抽取中文字符16进制字节的后两位,也就是=E8等号后面的两位,
                        // 三个代表一个中文字符
                        char c16_6;
                        char c16_7;
                        if (s16.charAt(6) >= 97 && s16.charAt(6) <= 122)
                        {
                            c16_6 = (char) (s16.charAt(6) - 32);
                        }
                        else
                        {
                            c16_6 = s16.charAt(6);
                        }
                        if (s16.charAt(7) >= 97 && s16.charAt(7) <= 122)
                        {
                            c16_7 = (char) (s16.charAt(7) - 32);
                        }
                        else
                        {
                            c16_7 = s16.charAt(7);
                        }
                        sb.append("=" + c16_6 + c16_7);
                    }
                }
            }
        }
        return sb.toString();
    }

    public  static String qpDecoding(String str,String charset)
    {
        if (str == null)
        {
            return "";
        }
        try
        {
            StringBuilder sb = new StringBuilder(str);
            for (int i = 0; i < sb.length(); i++)
            {
                if (sb.charAt(i) == '\n' && sb.charAt(i - 1) == '=')
                {
                    // 解码这个地方也要修改一下
                    // sb.deleteCharAt(i);
                    sb.deleteCharAt(i - 1);
                }
            }
            str = sb.toString();
            byte[] bytes = str.getBytes(StandardCharsets.US_ASCII);
            if(bytes.length == 0){
                return "";
            }
            for (int i = 0; i < bytes.length; i++)
            {
                byte b = bytes[i];
                if (b != 95)
                {
                    bytes[i] = b;
                }
                else
                {
                    bytes[i] = 32;
                }
            }
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            for (int i = 0; i < bytes.length; i++)
            {
                int b = bytes[i];
                if (b == '=')
                {
                    try
                    {
                        int u = Character.digit((char) bytes[++i], 16);
                        int l = Character.digit((char) bytes[++i], 16);
                        if (u == -1 || l == -1)
                        {
                            continue;
                        }
                        buffer.write((char) ((u << 4) + l));
                    }
                    catch (ArrayIndexOutOfBoundsException e)
                    {
                        e.printStackTrace();
                    }
                }
                else
                {
                    buffer.write(b);
                }
            }
            return new String(buffer.toByteArray(), charset);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return "";
        }
    }
}

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值