Search code examples
javaemailapache-commons-email

Apache Commons Email and Reusing SMTP Connections


Currently I am using Commons Email to send email messages, but I have not been able to find a way to share smtp connections between emails sent. I have code like the following:

    Email email = new SimpleEmail();
    email.setFrom("example@example.com");
    email.addTo("example@example.com");
    email.setSubject("Hello Example");
    email.setMsg("Hello Example");
    email.setSmtpPort(25);
    email.setHostName("localhost");
    email.send();

Which is very readable, but is slow when I do a large amount of messages, which I believe is the overhead of reconnecting for each message. So I profiled it with the following code and have found that using the reusing the Transport makes things about three times faster.

    Properties props = new Properties();
    props.setProperty("mail.transport.protocol", "smtp");
    Session mailSession = Session.getDefaultInstance(props, null);
    Transport transport = mailSession.getTransport("smtp");
    transport.connect("localhost", 25, null, null);

    MimeMessage message = new MimeMessage(mailSession);
    message.setFrom(new InternetAddress("example@example.com"));
    message.addRecipient(Message.RecipientType.TO, new InternetAddress("example@example.com"));
    message.setSubject("Hello Example");
    message.setContent("Hello Example", "text/html; charset=ISO-8859-1");

    transport.sendMessage(message, message.getAllRecipients());

So I was wondering if there was a way to make Commons Email reuse an SMTP connection for multiple email sendings? I like the Commons Email API better, but the performance is kind of painful.

Thanks, Ransom


Solution

  • I came up with the following solution after digging into the commons source itself. This should work, but there may be better solutions I do not know of

        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "smtp");
        Session mailSession = Session.getDefaultInstance(props, null);
        Transport transport = mailSession.getTransport("smtp");
        transport.connect("localhost", 25, null, null);
    
        Email email = new SimpleEmail();
        email.setFrom("example@example.com");
        email.addTo("example@example.com");
        email.setSubject("Hello Example");
        email.setMsg("Hello Example");
        email.setHostName("localhost"); // buildMimeMessage call below freaks out without this
    
        // dug into the internals of commons email
        // basically send() is buildMimeMessage() + Transport.send(message)
        // so rather than using Transport, reuse the one that I already have
        email.buildMimeMessage();
        Message m = email.getMimeMessage();
        transport.sendMessage(m, m.getAllRecipients());