使用 java 邮件发送批量邮件花费的时间太长
Sending bulkemails with java mail takes too long
我必须要处理以下情况。我想用 java 邮件客户端发送群发邮件。这意味着我想一次发送很多电子邮件。将它们全部放在收件人字段中的意见是毫无疑问的,因为没有收件人必须看到对方(密件抄送不起作用,因为您仍然看到收件人)。
所以我要做的是,打开一个新的 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
class 的抽象方法,因此使用 com.sun.mail.smtp
中的 SMTPTransport
的实现就我而言。
没有我的问题:transport.connect()
的连接时间大约需要 5 秒,sendMessage
的发送时间也是如此。这意味着,如果我向 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 秒。对于整个请求,每次上传都会花费大量时间。
因此,在不发送附件的情况下,请求不会花费太多时间。所以我的实现没有问题,而不是每次都上传附件
我必须要处理以下情况。我想用 java 邮件客户端发送群发邮件。这意味着我想一次发送很多电子邮件。将它们全部放在收件人字段中的意见是毫无疑问的,因为没有收件人必须看到对方(密件抄送不起作用,因为您仍然看到收件人)。
所以我要做的是,打开一个新的 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
class 的抽象方法,因此使用 com.sun.mail.smtp
中的 SMTPTransport
的实现就我而言。
没有我的问题:transport.connect()
的连接时间大约需要 5 秒,sendMessage
的发送时间也是如此。这意味着,如果我向 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 秒。对于整个请求,每次上传都会花费大量时间。 因此,在不发送附件的情况下,请求不会花费太多时间。所以我的实现没有问题,而不是每次都上传附件