java - 提高发送java邮件的速度

标签 java sql multithreading email smtp

我用 Java 编写了一段代码,使用 Java 邮件通过 smtp 服务器发送邮件。发件人和收件人的电子邮件地址以及邮件的主题和正文都保存在数据库 (sql) 中。但是,以这种方式发送邮件非常慢。我必须发送大量邮件(大约 300 封邮件/秒)。如何提高使用多线程发送邮件的速度?

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import oracle.jdbc.OraclePreparedStatement;

public class mainclass {

Properties emailProperties;
Session mailSession;
MimeMessage emailMessage;



public static void main(String args[]) throws AddressException,
        MessagingException {
            OraclePreparedStatement pst;
            Connection con;
            String userna;
            con = connectDB.connect();
            try {
                    Statement st = con.createStatement();
                    String sm = "SELECT * FROM EmailQueue WHERE sent = 'no'";
                    ResultSet res = st.executeQuery(sm);
                    while (res.next()) {
                        System.out.println(res.getString("from_email_address") + " " + res.getString("to_email_address"));
                        String id = res.getString("id");
                        String toEmails = res.getString("to_email_address");
                        String emailSubject = res.getString("subject");
                        String emailBody = res.getString("body");
                        String emailHost = "smtp.gmail.com";
                        String fromUser = res.getString("from_email_address");
                        String fromUserEmailPassword = res.getString("password");
                        mainclass javaEmail = new mainclass();
                        javaEmail.setMailServerProperties();
                        javaEmail.createEmailMessage(toEmails, emailSubject, emailBody);
                        javaEmail.sendEmail(emailHost, fromUser, fromUserEmailPassword);
                        Statement sn = con.createStatement();
                        String up = "Update EmailQueue set sent='yes' where id='"+id+"'";
                        sn.executeQuery(up);
                    }

        } catch(Exception e) {
            System.out.println("problem");
        }


}

public void setMailServerProperties() {

    String emailPort = "587";//gmail's smtp port

    emailProperties = System.getProperties();
    emailProperties.put("mail.smtp.port", emailPort);
    emailProperties.put("mail.smtp.auth", "true");
    emailProperties.put("mail.smtp.starttls.enable", "true");

}

public void createEmailMessage(String toEmails, String emailSubject, String emailBody) throws AddressException,
        MessagingException {

    mailSession = Session.getDefaultInstance(emailProperties, null);
    emailMessage = new MimeMessage(mailSession);

        emailMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmails));


    emailMessage.setSubject(emailSubject);
    emailMessage.setContent(emailBody, "text/html");//for a html email
    //emailMessage.setText(emailBody);// for a text email

}

public void sendEmail(String emailHost, String fromUser, String fromUserEmailPassword) throws AddressException, MessagingException {


    Transport transport = mailSession.getTransport("smtp");

    transport.connect(emailHost, fromUser, fromUserEmailPassword);
    transport.sendMessage(emailMessage, emailMessage.getAllRecipients());
    transport.close();
    System.out.println("Email sent successfully.");
}

}

最佳答案

快速发送大量电子邮件的关键是多线程——在您的 Java 代码和电子邮件服务器的配置中。

当您通过 JavaMail 发送电子邮件时,您实际上只是在向您的 SMTP 电子邮件服务器提交一条消息。您的 SMTP 服务器然后查找接收域的 MX 地址(电子邮件地址中“@”之后的部分)以获得接收 SMTP 服务器的 IP 地址。然后它开始与接收方 SMTP 服务器进行对话,最终导致消息被传输。由于多种原因,此过程可能会非常缓慢。 - 查找接收服务器 IP 地址的过程可能需要一些时间 - 与接收 SMTP 服务器的对话可能非常慢,具体取决于其负载和策略。有些对话实际上可能需要几分钟。

因此,要加快电子邮件应用程序的吞吐量,您应该: 1) 确保您的 SMTP 服务器有本地缓存​​名称服务器。这将使它识别接收 SMTP 的 IP 的过程更快。基本上,缓存名称服务器会在本地记住过去的查找请求,因此对同一域的后续请求要快得多(可能快 100 倍)。换句话说,一旦您查找了“gmail.com”的接收 IP 地址,您就无需再次查找,直到其 TTL 到期。在 Red Hat Linux 上,您可以通过“yum install caching-nameserver”将绑定(bind)配置为缓存名称服务器。

2) 将您的 SMTP 服务器配置为具有许多 线程。由于大多数时候,您的 SMTP 服务器将等待其他服务器进行他们这边的“对话”,它可以有效地同时进行数百个对话。我使用 Postfix 因为它快速可靠。默认情况下,Postfix 配置为具有 100 个并发 SMTP 进程。我将其提高到 300 或更多。在 Postfix 中,您可以使用 default_process_limit 设置配置此进程限制。

3) 调整您的 SMTP 服务器以考虑到某些接收服务器会非常慢或完全没有响应。例如,默认情况下,Postfix 配置为等待 300 秒(五分钟!)让接收服务器响应其初始“HELO”。我通过设置 smtp_helo_timeout=100s 的配置选项将这个时间缩短到 100 秒。由于接收服务器速度慢而未能成功发送的邮件只会由您的 SMTP 服务器排队等待稍后重试。

4) 在使用 JavaMail 时使用多线程。在我的 Java 代码中创建多线程时,我已经加快了 10 倍的速度。这样,我的 SMTP 服务器就可以同时进行许多对话。

关于java - 提高发送java邮件的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28531076/

相关文章:

c - 为什么我的C多线程调度程序出现段错误(核心转储)

sql - 在存储过程中验证用户的最简单方法?

multithreading - 作业的拆分/聚集模式

java - 如何在maven中部署父项目打包war

java - 在 Java 中通过标题解析特定列

mysql - Many 2 Many 中的递归方式排序

c++ - MS Access 从 C++ 应用程序查询 ORDER BY 日期

java - 等待所有阻塞队列元素取出后处理

Java数组创建

java - 如何指示表中的列是可排序的(UI 设计问题)?