我怀疑我使用了错误的 Apache Common Email 库来发送带有附件的电子邮件。 有时我会收到“打开的文件太多”错误,如果我使用lsof检查打开的文件,我会发现附件文件被打开了多次:
图像1.png 图片2.png 图片1.png ...
所以我怀疑我没有正确释放文件(或者没有关闭某些资源)。也可能该软件可以工作,但如果外部 SMTP 服务器发生故障(连接异常),我的代码不会释放一些资源。
来源:
/* Async Thread to send email */
Thread t = new Thread(){
@Override
public void run(){
try{
task(request,idNewsletter);
}
catch (Exception e){
log.error("Error " + e);
}
}
};
t.start();
[...]
任务方法:
ExecutorService executor = Executors.newFixedThreadPool(10);
[...]
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
for (int i = 0; i < dests.length; i++) {
HtmlEmail htmlEmail = getHtmlMail([...]);
ArrayList<InternetAddress> dest = new ArrayList<InternetAddress>();
InternetAddress add = new InternetAddress();
add.setAddress(dests[i]);
dest.add(add);
htmlEmail.setBcc(dest);
htmlEmail.setMailSession(getEmailSession());
htmlEmail.buildMimeMessage();
Callable<Integer> worker = new EmailService(htmlEmail,i);
Future<Integer> future = executor.submit(worker);
list.add(future);
}
try {
executor.shutdown();
executor.awaitTermination(28800, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.error("Error=" + e);
}
finally {
if (!executor.isTerminated()) {
log.error("Task cancelled");
}
executor.shutdownNow();
}
getHtmlEmail 方法
private static URL image;
static {
image= (new File("somepath").toURI().toURL());
}
private HtmlEmail getHtmlMail([...]){
HtmlEmail htmlEmail = new HtmlEmail();
htmlEmail.setCharset("UTF-8");
htmlEmail.setSubject("someSubject");
htmlEmail.setFrom(from);
htmlEmail.setSentDate(new java.util.Date());
[...]
String cidImage= htmlEmail.embed(image, "Email image");
text= text.replace("cid:image", "cid:" + cidImage);
[...] /* Other attachments */
htmlEmail.setHtmlMsg(text);
return htmlEmail;
}
getEmailSession 方法
private Session getEmailSession() throws Exception{
if (mailSession != null)
return mailSession;
else {
InitialContext ic = new InitialContext();
mailSession = (Session) ic.lookup("someJNDI");
mailSession.getProperties().put("mail.smtp.connectiontimeout", 1000);
mailSession.getProperties().put("mail.smtp.timeout", 5000);
return mailSession;
}
}
以及发送电子邮件的方法
@Override
public Integer call() throws Exception {
try{
htmlEmail.sendMimeMessage();
}
catch(Exception e){
log.error("Error=" + e);
htmlEmail=null;
return new Integer(0);
}
return new Integer(1);
}
有什么提示吗?
提前致谢 安德里亚
最佳答案
我相信这就是问题所在:
static {
image= (new File("somepath").toURI().toURL());
}
它是静态
。这是您遇到的并发问题。
它总是在那里。
这就是我认为正在发生的事情。假设它位于一个名为 Url
的类中,并且您有一个返回该值的非静态 getUrl()
。
如果您这样做:
Url url1 = new Url();
Url url2 = new Url();
url1.getUrl();
url2.getUrl();
然后他们每个人都应该返回一个不同的 url 实例。但是,您将 url
属性初始化为 static
,因此实际情况是Url 的所有实例都只有一个 url。 url 属性不属于每个对象,而仅属于类本身。
因此,当您尝试调用它时,它们都会一次又一次地尝试访问该文件,因为它从来没有“创建”,也没有在每个实例中初始化。将其视为始终存在的东西,因为类本身拥有它,而不是实例,从而给您带来打开文件过多
错误。
所以我建议你将其从静态中删除。也许你可以做这样的事情:
class Url{
private final URL url;
public Url() {
url= (new File("somepath").toURI().toURL());
}
}
然后只需在您想要的任何地方使用该 url
属性即可。
关于java - 并发发送带附件的 HtmlEmail 和 "Too many open files"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51707078/