使用java mail发送大量电子邮件花费的时间太长
我必须了解以下情况。我想用java邮件客户端发送大量电子邮件。这意味着我想一次发很多电子邮件。将它们全部放在收件人字段中的意见是毫无疑问的,因为没有收件人必须看到对方(密件抄送不起作用,因为您仍然可以看到收件人)。 因此,我要做的是,打开一个新的使用java mail发送大量电子邮件花费的时间太长,java,email,smtp,jakarta-mail,Java,Email,Smtp,Jakarta Mail,我必须了解以下情况。我想用java邮件客户端发送大量电子邮件。这意味着我想一次发很多电子邮件。将它们全部放在收件人字段中的意见是毫无疑问的,因为没有收件人必须看到对方(密件抄送不起作用,因为您仍然可以看到收件人)。 因此,我要做的是,打开一个新的Transport连接,对每个收件人使用sendMessage(),然后关闭Transport连接。以下是代码片段: Session session = Session.getInstance(smtpProps, new javax.mail.Auth
Transport
连接,对每个收件人使用sendMessage()
,然后关闭Transport
连接。以下是代码片段:
Session session = Session.getInstance(smtpProps, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(authUser, authPass);
}
});
InputStream is = IOUtils.toInputStream(eml, "UTF-8");
MimeMessage message = new MimeMessage(session, is);
Transport transport = session.getTransport("smtp");
transport.connect(smtpServer, smtpPort, smtpUser, smtpPass);
Address[] recipients = message.getRecipients(RecipientType.TO);
for(Address address : recipients) {
message.setRecipient(RecipientType.TO, address);
transport.sendMessage(message, new Address[]{ address });
}
transport.close();
请记住,sendMessage()
方法是javax.mail.Transport
类的抽象方法,因此在我的示例中使用了com.sun.mail.smtp
中的SMTPTransport
我的问题没有:在transport.connect()
上的连接时间大约需要5秒,在sendmages
上的发送时间也需要5秒。这意味着,如果我向10个收件人发送电子邮件,需要5+(10*5)=~55秒。这是很长的一段时间,想想我们有1000个接受者
这正常吗?或者,你知道是什么导致了这个问题,它持续了这么长时间吗?是否有其他(好的)sendMessage()
实现,或者该方法的默认用法是SMTPTransport
信息:for循环分别在单独的线程中运行,因此电子邮件在后台发送。整个servlet包含这个被剪断的部分,它运行在服务器集群上的docker容器中。因此,如果我将其并行化,或者使用多个线程,我不知道该行为如何与集群上的其他servlet一致。而不是使用:
Address[] recipients = message.getRecipients(RecipientType.TO);
for(Address address : recipients) {
message.setRecipient(RecipientType.TO, address);
transport.sendMessage(message, new Address[]{ address });
}
你应使用:
Address[] recipients = message.getRecipients(RecipientType.TO);
message.addRecipients(RecipientType.CC, recipients);
这将向邮件服务器发送一个邮件请求,并将节省大量时间和请求。我想我找到了解决问题的方法。 连接花费如此多的时间似乎是正常的。 我的问题是,附件必须每次上传到smtp服务器,大约4秒。对于整个请求,每次上传都会占用大量时间。
因此,如果不发送附件,请求不会花费太多时间。因此,在我的实现中没有问题,而不是每次都上传附件。您尝试过将其并行化吗?我知道这是一个带有一些参数的完整方法,例如
authUser
和authPass
以及电子邮件正文eml
(?)似乎很容易做到。只需尝试从线程池执行器或使用java 8parallelStream()
lambda调用此方法。这里有很多例子,事实上,你可以尝试用一个parallelStream()
来更改for
循环,这应该可以做到。@Marc:是的,这只是从一个更大的方法中剪下来的。这个循环已经在一个单独的线程中运行,因此电子邮件是在后台发送的。整个servlet在集群中的docker容器中运行。我不知道与其他servlet一致的行为是如何发生的,如果我有很多线程,这可能会导致问题,我不清楚。我用这些信息展开我的问题。DNS查找可能会影响某些计算机上的性能。为mail.smtp.localhost
设置会话属性,以防止在HELO
命令上查找名称。设置mail.from
或mail.host
(不是协议版本)的会话属性,因为这将阻止在MimeMessage.updateMessageID()上查找名称。您看到了吗?不,我看不到。请阅读我的整个问题,而不仅仅是代码部分。请阅读第四句,然后你知道为什么你的答案不是我问题的答案。你应该考虑更大的问题,比如如果你真的需要上传或下载一个大的eml文件怎么办?