提高发送java邮件的速度

时间:2015-02-15 20:57:50

标签: 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.");
}

}

2 个答案:

答案 0 :(得分:2)

快速发送大量电子邮件的关键是多线程 - 无论是在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代码中创建多线程的过程中,我加快了很多因素。这样,我的SMTP服务器会立即进行多次对话。

答案 1 :(得分:0)

多线程发送邮件的过程只会使成千上万的请求破坏您的邮件服务器。

当您发送电子邮件时(例如,使用JavaMail),您只需向邮件服务器提交新邮件。它是实际将邮件发送给收件人的邮件服务器。你无法在Java方面做任何事情来提高交付速度。