0x00(测试条件)
附件名:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt
0x01(现象)
新浪邮箱解析出错:
QQ邮箱解析出错:
0x02(分析问题)
本地没问题,到 Linux 环境才出错。所以抓了本地的包和 Linux 下的包比较。
本地的包(之前用比较长的中文名测试抓的包):
------=_Part_18_1324418920.1488440125843
Content-Type: application/octet-stream;
name="=?UTF-8?Q?=E4=B8=AD=E6=96=87=E5=AD=97=E7=AC=A6201711=2Edocx?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="=?UTF-8?Q?=E4=B8=AD=E6=96=87=E5=AD=97=E7=AC=A6201711=2Edocx?="
Linux 的包:
------=_Part_0_528597028.1488450122516
Content-Type: text/plain; charset=us-ascii;
name*0=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
name*1=a.txt
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename*0=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;
filename*1=a.txt
可以看到问题是文件名太长被拆分了
0x03(查找根源)
看 Java 代码
String encodeName = MimeUtility.encodeWord(name); UrlResource inputStreamSource = new UrlResource(attach.getUrl()); helper.addAttachment(encodeName, inputStreamSource); // 自己的业务代码
addAttachment(attachmentFilename, inputStreamSource, contentType); // 跟进去
addAttachment(attachmentFilename, dataSource); // 跟进去
mimeBodyPart.setFileName(MimeUtility.encodeText(attachmentFilename)); // 跟进去
setFileName(this, filename); // 跟进去
part.setHeader("Content-Disposition", cd.toString()); // 跟进去
sb.append(list.toString(sb.length() + 21)); // 跟进去
if (value.length() > 60 && splitLongParameters && encodeParameters) { int seg = 0; name += "*"; // 省略...
已经看出是怎么回事了
0x04(解决)
在 Main方法下加
System.setProperty("mail.mime.splitlongparameters", "false"); // linux 会默认为 true,会截断附件名
0x05(PS)
这是 RFC2231 的规定,估计国内的还不支持(个人猜想)
0x06(走过的弯路)
之前没头绪。以为是 Linux 的限制;也怀疑过“MimeUtility.encodeWord(name)”的问题。
跟踪源码的时候看错了 jar 包,应该是 com.sun.mail:javax.mail:1.5.6,还不是 javax.mail:mail:1.4.5