java - 并发发送带附件的 HtmlEmail 和 "Too many open files"错误

标签 java apache email

我怀疑我使用了错误的 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/

相关文章:

java - 泛型类中的编译错误

eclipse - 如何启动eclipse中打包的apache tomcat?

android - 应用程序发送的电子邮件附件与发送的文件名称不同

c# - 使用C#在电子邮件中取消订阅选项

linux - 设置SSL/需要先设置邮件

excel - 在java中对excel单元格进行分组

java - string.format() 中是否有 "%"空格符号?

java - 如何关闭此 javadoc 警告 : @return tag has no arguments

java - 两阶段提交-如何测试

css - Django 和 Apache/mod_wsgi 不呈现 css