【发布时间】:2014-02-02 22:16:07
【问题描述】:
我正在尝试发送带有附件的电子邮件。附件是即时生成的,因此没有文件,我无法在文件系统上创建临时文件。
InputStream attachment
我尝试过直接使用 JavaMail 和 apache.commons.mail。两者我都有相同的结果。浏览器停留为“等待本地主机”需要 6 分钟。我怀疑问题是邮件库并不真正知道 InputStream 有多大(或者他们没有正确处理 InputStream),所以他们等到某个超时然后发送邮件。我已经对文件进行了测试(通过 FileDataSource 和其他),它工作正常,但不是 InputStream...
有什么方法可以让它工作而不会让用户永远等待吗?当然减少 timeOut 不是一个好的解决方案,因为我不知道连接的速度和速度有多快另一方面,我不想让快速用户等待发送 200KB 的电子邮件。
// Create the email message
MultiPartEmail email2 = new MultiPartEmail();
email2.setHostName(host);
email2.setAuthenticator(new DefaultAuthenticator(username, password));
email2.setSSLOnConnect(true);
email2.setFrom(username);
email2.setSmtpPort( Integer.parseInt(port) );
email2.addTo(to);
email2.setSubject("MAIL");
email2.setMsg("Text");
DataSource source = new ByteArrayDataSource(attachment, "application/pdf");
// add the attachment
email2.attach(source, "somefile.pdf", "Description of some file");
email2.send();
此代码将正确发送邮件...但在 6 分钟或更长时间后。
编辑
我在代码中放置了一些痕迹:
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.println("Start: " + dateFormat.format(date));
// Create the email message
MultiPartEmail email2 = new MultiPartEmail();
email2.setHostName(host);
email2.setAuthenticator(new DefaultAuthenticator(username, password));
email2.setSSLOnConnect(true);
email2.setFrom(username);
email2.setSmtpPort( Integer.parseInt(port) );
email2.addTo(emailTO);
email2.setSubject("MAIL");
email2.setMsg("Text");
date = new Date();
System.out.println("Before DataSource: " + dateFormat.format(date));
DataSource source = new ByteArrayDataSource(attachment, "application/pdf");
date = new Date();
System.out.println("After DataSource: " + dateFormat.format(date));
// add the attachment
email2.attach(source, "somefile.pdf", "Description of some file");
date = new Date();
System.out.println("Before send(): " + dateFormat.format(date));
email2.send();
date = new Date();
System.out.println("After send(): " + dateFormat.format(date));
结果是这样的:
Start: 2014/02/24 16:18:01
Before DataSource: 2014/02/24 16:18:01
After DataSource: 2014/02/24 16:18:01
Before send(): 2014/02/24 16:18:01
Feb 24, 2014 4:18:01 PM org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage getColorSpace
INFO: About to return NULL from unhandled branch. filter = COSName{DCTDecode}
After send(): 2014/02/24 16:26:35
如果我评论 email2.attach(...) 我会得到:
Start: 2014/02/24 16:28:56
Before DataSource: 2014/02/24 16:28:56
After DataSource: 2014/02/24 16:28:56
Before send(): 2014/02/24 16:28:56
After send(): 2014/02/24 16:29:27
当然需要很长的时间,但这是可以接受的......
现在,很明显问题与附件有关。不过,我不确定收到 PDFBox 警告是什么...
编辑 2
我现在正在测试没有附件,发送电子邮件只需要 5 秒...所以它看起来确实与访问 InputStream 的方式有关。
编辑 3
我启用了调试,似乎附件中消耗了时间。我看到 send() 做了什么并打印了:
------=_Part_0_2141791733.1395266799862
Content-Type: application/pdf; name="my.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="my.pdf"
Content-Description:
JVBERi0xLjQKJfbk/N8KMSAwIG9iago8PAovTWFya0luZm8gMiAwIFIKL01ldGFkYXRhIDMgMCBS
... 然后 send() 将附件内容一点一点地打印出来,如下所示:
MhKxjVRnwA6I8BisAX1VTXc0hw1DXO0lBcQJDQpWFZPU3oX2YogU3Y0SbgFxKBCJWzUEqfJIQ5Bh
GrYDx1o3JOIYHZPnVRZHa4EA0FqGxiZk6MdkEfYakPO4MW1jXIjeKFMxdL1XY84nrGDMwoyCkC3N
TJOAJITplbIewNEXv6u8AIf64hiZIm+x4jyFOxzk5DzfSONJiDiKbtozF+Yz+g90lJOCLiRFneuV
3AYDQAD1gnW+odwoSVBAUezLL5Zwue1yttDySw5zVsaE9j7kv9mHpOlnTephlZR5fiu/f+XEOb/O
qQ6suP2zOl/3KRw+OMiXC5hNGlAca7d2XWDMLIiQs45yUsCnljRLVdYFKz7Zg6zcsiH9kaupwOe4
ifPEiXe/8LEok2So8o3Bp5XysDadYxsllfVLlNdLXlQc+2R+kdFHam5ydBm5HkYl5ZCwF2vPKpvU
然后它需要几秒钟......并打印另一个块。这个过程持续大约 6 分钟。直到完成:
MjRDODdCODVGMEEyQjBBMzVDQj4gPEM5MjBBRjU5Q0MxOEM2NDI5MDM4REIzMEI2OUE0REQ5Pl0K
L1Jvb3QgMSAwIFIKL0luZm8gNyAwIFIKL1hSZWZTdG0gMTYxOAo+PgpzdGFydHhyZWYKNDEzNjI5
CiUlRU9GCg==
------=_Part_0_690515382.1395264718480--
.
250 OK id=4WQO3h-0004D1-VQ
QUIT
221 mail2.... closing connection
我猜InputStream 有问题。没有附件或从文件中获取附件,它工作得很好而且很快。附件只有 ~0.4MB
也许InputStream 的创建方式有些问题。但这似乎很奇怪,因为我使用完全相同的方法下载 PDF,并且下载效果很好。
ByteArrayOutputStream os = new ByteArrayOutputStream();
pd.save(os);
return new ByteArrayInputStream( os.toByteArray() );
【问题讨论】:
-
InputStream 是从哪里来的?你真的确定时间花在了 send() 中吗?而不是例如构造 ByteArrayDataSource?
-
我放了一些日志,时间花在了send()中。 INpuTStream 来自另一个动态生成 PDF 的函数(也是我创建的)。
标签: java jakarta-mail inputstream attachment