Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用javax.mailapi高效地发送批量邮件&;我们可以使用重用认证会话来提高速度吗?_Java_Email_Smtp_Jakarta Mail - Fatal编程技术网

如何使用javax.mailapi高效地发送批量邮件&;我们可以使用重用认证会话来提高速度吗?

如何使用javax.mailapi高效地发送批量邮件&;我们可以使用重用认证会话来提高速度吗?,java,email,smtp,jakarta-mail,Java,Email,Smtp,Jakarta Mail,我能够使用javax.mailapi发送邮件。但这里的问题是,平均每封邮件发送到目的地大约需要4.3秒 如果我按顺序发送20封邮件,大约需要86.599秒。根据我的要求,这种方法行不通。我正在寻找一种方法,可以在更短的时间内发送大量邮件 当我查看调试日志时,API正在尝试对SMTP服务器发送的每条消息进行身份验证。但我只创建了一次会话,并对我发送的所有邮件使用相同的会话。现在我的问题是,每次向smtp服务器进行身份验证时,这不是一个开销很大的过程吗。难道没有更好的方法吗 下面是您可能会觉得有用的

我能够使用javax.mailapi发送邮件。但这里的问题是,平均每封邮件发送到目的地大约需要4.3秒

如果我按顺序发送20封邮件,大约需要86.599秒。根据我的要求,这种方法行不通。我正在寻找一种方法,可以在更短的时间内发送大量邮件

当我查看调试日志时,API正在尝试对SMTP服务器发送的每条消息进行身份验证。但我只创建了一次会话,并对我发送的所有邮件使用相同的会话。现在我的问题是,每次向smtp服务器进行身份验证时,这不是一个开销很大的过程吗。难道没有更好的方法吗

下面是您可能会觉得有用的日志跟踪

250-AUTH LOGIN PLAIN XOAUTH XOAUTH2
250 ENHANCEDSTATUSCODES
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH XOAUTH2"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Attempt to authenticate
DEBUG SMTP: check mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
请让我知道你对这件事的想法,我们非常感谢你对这件事的帮助


> NalndRa/P>< P>不知道标准java邮件API是否允许您尝试实现(会话重用),但可以考虑使用多线程:


我将使用线程池并向其提交邮件发送作业。然后在作业类代码中执行任何错误处理/重新发送,该代码由线程池异步执行,主线程可以继续执行其他操作。提交作业只需毫秒。我用Java实现线程池已经有一段时间了,但我记得它相当简单和直接。如果你在谷歌上搜索“Java线程池”,你会发现很多资料。

你是如何发送这些信息的?建议使用static
Transport.send
方法为每条消息打开一个新的连接,因为它是一种方便的方法,可以创建一个合适的
Transport
实例,连接它,调用
sendMessage
,然后再次关闭连接。如果您从
会话
获得自己的
传输
实例,您可以连接一次,然后反复调用
发送消息
在一个连接上发送多条消息,最后关闭它。类似于(未经测试的):

更新为使用“尝试使用资源”块:

try (Transport t = session.getTransport()) {
    t.connect();
    for(Message m : messages) {
        m.saveChanges();
        t.sendMessage(m, m.getAllRecipients());
    }
}

我在工作中也有同样的要求。我必须发送批量电子邮件和独立电子邮件。我没有找到简单而令人满意的答案:批量电子邮件可以使用单个连接发送,但独立电子邮件不能,除非我创建一个异步缓冲以批量发送电子邮件

最后但并非最不重要的一点是,在短时间内使用大量的
传输
连接可能导致
不再有可用的套接字句柄
,因为所有端口都卡在
时间等待
状态

我最后得出结论,最好的是SMTP连接池,因为不存在使用Apache公共池和Java Mail的库(至少是免费的):

//Declare the factory and the connection pool, usually at the application startup
SmtpConnectionPool smtpConnectionPool = new SmtpConnectionPool(SmtpConnectionFactoryBuilder.newSmtpBuilder().build());

//borrow an object in a try-with-resource statement or call `close` by yourself
try (ClosableSmtpConnection transport = smtpConnectionPool.borrowObject()) {
    MimeMessage mimeMessage = new MimeMessage(session);
    MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false);
    mimeMessageHelper.addTo("to@example.com");
    mimeMessageHelper.setFrom("from@example.com");
    mimeMessageHelper.setSubject("Hi!");
    mimeMessageHelper.setText("Hello World!", false);
    transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
}

//Close the pool, usually when the application shutdown
smtpConnectionPool.close();

您可以使用线程池,因为它提供了非常好的性能

try  {
    ExecutorService executor = Executors.newFixedThreadPool("no. of threads"); // no. of threads is depend on your cpu/memory usage it's better to test with diff. no. of threads.
    Runnable worker = new MyRunnable(message); // message is the javax.mail.Message
    executor.execute(worker);
    executor.shutdown();
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}

上述答案要么不相关,要么过于复杂,难以实施。所以这里我发布了一个最简单的解决方案,可以在SpringBoot中发送大量电子邮件

只用

mimeMessageHelper.setBcc(emailList);
在哪里,

mimessagehelper
mimessagehelper
emailList
String[]emailList

注意:

确保您没有使用

mimeMessageHelper.setTo(emailList)
否则,它将在收件人收到的电子邮件中显示所有收件人的电子邮件地址


如需更多参考,可帮助您了解如何在Spring Boot中发送电子邮件

通过利用sendmail发送批量电子邮件。抱歉,我无法在此处共享我的代码,也无法使用sendmail。您好,FelixD,感谢您的回答。我主要寻找会话重用bcz身份验证每次都是一个开销过程。我的主要目标是将发送邮件所需的时间从4秒减少到1秒左右。您建议使用theads,但这不会缩短从src系统向目的地发送邮件的时间。嗨,Narenda,不用担心,谢谢您的评论。我明白你的意思——不幸的是,我不能真正帮助你更高级地使用Java邮件API,我只是用它完成了简单的发送。我希望我关于多线程的建议可能会对其他人有所帮助,因为在某些情况下,多线程可以解决问题(例如,当邮件发送使主应用程序忙得太久等)。当然,通过我的方法,另一端邮件服务器上的负载也不会减少……感谢FelixD的回复。正如Ian Robert在上面的回答中所建议的,使用sendMessage对我的场景非常有用,它可以减少邮件传递的时间,因为它可以重用现有的会话对象。但实现它并不像伊恩·罗伯特所说的那么容易。你是对的。当我写最后一条评论时,我没有注意到伊恩·罗伯特的回答。他写的东西看起来很有趣,也许我也需要一些时间谢谢你的回答。目前我正在使用Transport.send()。我将使用session.getTransport().sendMessage(message,addressarray)测试代码@Narendra虽然没有那么简单,但我已经用一个更详细的例子编辑了我的答案。谢谢你的代码片段。我用sendMessage方法尝试了我的代码,现在发送邮件的时间比使用send()减少了一半。但是我这里有一个问题:savechanges()有什么用途?调用savechanges很昂贵,对吗?在什么情况下我们应该称之为?请让我知道。@Narendra如果您想在一个连接上批处理多条消息,我把它放进去是为了显示静态
send
方法的最小更改。静态
send
会在发送邮件之前调用
saveChanges
,如果您知道您的邮件标题已经是最新的,您可能可以避免这种情况发生。@Ian Roberts,我只是想澄清一下,在您的回答中,这是否意味着多个电子邮件地址
mimeMessageHelper.setTo(emailList)