How to send email in java using asynchronous API

18,013

Solution 1

Setup an Executor bean that uses a thread pool executor in your spring context and use it to enqueue a work item that will send the email. It will then be dispatched on a thread pool thread asynchronously and therefore your request thread will not block.

Solution 2

In Spring MVC we have TaskExecutor which makes sending asynchronous mails easy.

<!-- Mail sender bean -->
 <bean class="org.springframework.mail.javamail.JavaMailSenderImpl" id="mailSender">
  <property name="host"><value>mail.test.com</value></property>
         <property name="port"><value>25</value></property>
         <property name="protocol"><value>smtp</value></property>
         <property name="username"><value>[email protected]</value></property>
         <property name="password"><value>pass</value></property>
         <property name="javaMailProperties">
             <props>
                 <prop key="mail.smtp.auth">true</prop>
<!--                  <prop key="mail.smtp.starttls.enable">true</prop> -->
                 <prop key="mail.smtp.quitwait">false</prop>
             </props>
         </property>
     </bean> 

<bean class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" id="taskExecutor">
     <property name="corePoolSize" value="5"></property>
     <property name="maxPoolSize" value="10"></property>
     <property name="queueCapacity" value="40"></property>
     <property name="waitForTasksToCompleteOnShutdown" value="true"></property>
    </bean>

Your java class should look like this:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.task.TaskExecutor;
import org.springframework.mail.MailParseException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

@Service("mailService")
public class MailService {
    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private TaskExecutor taskExecutor;

    private static Log log = LogFactory.getLog(MailService.class);

 /**
  * @param text - message
  * @param from - sender email
  * @param to - receiver email
  * @param subject - subject
  * @param filePath - file to attach, could be null if file not required
  * @throws Exception
  */
 public void sendMail(final String text,  final String from, final String to, final String subject, final File file) throws Exception {
   taskExecutor.execute( new Runnable() {
   public void run() {
    try {
      sendMailSimple(text, to, subject, file.getAbsolutePath());
    } catch (Exception e) {
     e.printStackTrace();
     log.error("Failed to send email to: " + to + " reason: "+e.getMessage());
    }
   }
  });
 }

  private void sendMailSimple(String text, String from, String to, String subject, String filePath) throws Exception { 
  MimeMessage message = mailSender.createMimeMessage();
  try {
   MimeMessageHelper helper = new MimeMessageHelper(message, true);
   helper.setFrom(from);
   helper.setTo(to);
   helper.setSubject(subject);
   helper.setText(text);
   if(filePath != null){
    FileSystemResource file = new FileSystemResource(filePath);
    helper.addAttachment(file.getFilename(), file);
   }
  } catch (MessagingException e) {
    throw new MailParseException(e);
  }
  mailSender.send(message);

  if(log.isDebugEnabled()){
   log.debug("Mail was sent successfully to: " + to + " with file: "+filePath);
  }
  }
}

Solution 3

The Google App Engine implementation of Javamail API allows you to send mail asynchronously, but I don't know if it is feasible to embed it in a servlet. Even if it is not feasible to use GAE like this, it proves that it is possible to implement a javamail provider that does asynchronous mail sending.

Another alternative is to set up local mail service to act as a relay for your Java application. If configured correctly, this should allow you to get messages off your hands in milliseconds. It can also take care of issues such as remote mail servers being temporarily down. The downside is that you have another service to maintain, and your Java application don't get any notification of failure to deliver mail to the ultimate recipients.

Share:
18,013
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin about 2 years

    I was trying to send email using simple method and it was very slower. and some told me to send email via Asynchronous API.

    This was my old question Email code makes the code slower in java spring MVC

    can anyone guide on this what is that and how will it make sending email faster