How to Send bulk mails using javax.mail API efficiently? & Can we use reuse authenticated sessions to improve speed?

How are you sending the messages? The JavaMail FAQ suggests that the static Transport.send method will open a fresh connection for each message, as it is a convenience method that creates a suitable Transport instance, connects it, calls sendMessage and then closes the connection again. If you get your own Transport instance from the Session you can connect once, then call sendMessage repeatedly to send several messages on the one connection, and finally close it. Something along the lines of (untested):

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

Updated to use try with resources block:

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

I got the same requirement at work. I must send bulk emails and standalone email. I do not find simple and satisfactory answer: bulk emails can be sent using a single connection but standalone email cannot until I create an asynchronous buffering to send emails in batch.

Last but not least, using a lot of Transport connection in a short time can lead to a no more socket handles are available because all ports are stuck in the TIME_WAIT state.

I finally conclude the best will be an SMTP connection pool and because no library exists (at least free) I create mine using Apache Common Pool and 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("[email protected]");
    mimeMessageHelper.setFrom("[email protected]");
    mimeMessageHelper.setSubject("Hi!");
    mimeMessageHelper.setText("Hello World!", false);
    transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
}

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