0

My server requires sending emails pretty frequently. The emails are heavy; they have attachments as well as inline images in them.

My present code blocks code until an email is sent. (loosing 5 to 6 seconds for every email)

What is the best approach for handling the emails with out blocking the main code flow?

If you are suggesting threads, please elaborate on how efficiently it could be handled?

Balaji Vignesh
  • 446
  • 1
  • 7
  • 19
  • 2
    Efficiently means? It can handled by single thread only. Add an extra thread for mail That is it. This is the generic approach which everyone follows. – Ria Sen Apr 21 '17 at 08:40
  • Thread are always the solution to execute heavy process without blocking the main thread.. and this would be as efficient as your code is ... if you have more than 1 mail to send at a time, use more than one thread (don't use an unlimited amount). But there is no more complet answer than this. Read a guide about threading if you need – AxelH Apr 21 '17 at 08:43
  • Please provide some more info. Are you using Spring, Java EE or another framework? Do you use java Mail API or some other library? – ipper Apr 21 '17 at 08:43
  • I use java mail API and Java EE. – Balaji Vignesh Apr 21 '17 at 09:00

2 Answers2

2

There are multiple ways to achieve this functionality.

Synchronous Call

This is the one which you are already using. Code (synchronously) invokes Java Mail API and waits for API to complete the execution. The process may take time depending on the complexity of building the email message (fetching records from Database, reading images/documents (attachments), communication with Mail Server etc.

Trade-offs

  1. For individual requests(web/desktop), response latency will increase based on the time it takes to construct and send email.
  2. An exception in sending email, may require redo of entire process (if retried).
  3. Transactional data (e.g. DB) may be rolled back, due to exception while sending email. This may not be desired behavior.
  4. Overall application latency will increase, if similar functionality is invoked by multiple users concurrently.
  5. Email retry functionality may not be possible, if email sending code is tightly coupled with other functional code.

Multithreading Approach

Create a separate thread to asynchronously send an email. Calling code need not have to wait for Email send functionality to complete and execute rest of the code. Ideally, should make use of ThreadPool, instead of blandly creating new threads.

Trade-offs

  1. Though, request latency will go down, it is still not reliable. Any exception occurred while constructing/sending email may result into, no email sent to user.

  2. Email sending functionality can't be distributed across multiple machines.

  3. Retry functionality is possible, since email code is separated into separate class. This class can be independently called, without a need of redoing other things.

Asynchronous Processing

Create a class, which accepts Email request and stores it in either database or messaging infrastructure (e.g. JMS). The message listeners will process the task as and when it arrives and update the status against each task.

Trade-offs

  1. Email requests can be processed in distributed mode.
  2. Retry email possible, without having any side effects.
  3. Complex implementation as multiple components are involved in processing, persisting email requests.
CuriousMind
  • 3,143
  • 3
  • 29
  • 54
  • So i think the best approach would be to combine asynchronous processing along with multi threading approach. Every email that needs to be sent has to be pushed to a database table1. Once the email is sent successfully, the record could be pushed to another table say table2. And all these could take place in a thread separately.. – Balaji Vignesh Apr 21 '17 at 12:24
  • You need not have to maintain separate table. Just have a status field in the same table with possible values like PENDING, FAILED, SENT etc. – CuriousMind Apr 24 '17 at 08:10
0

You can efficiently do this if you spawn a thread for every email you have to send.

One way to do it is as follows:


You would need a class that is just a pure extension of Thread:

public class MailSenderThread extends Thread {        
    @Override
    public void run() {
        try {
            // Code to send email
        } catch (Exception ex) {
            ex.printStackTrace();
        }    
    }    
}

And when you want to send email, you can do:

new MailSenderThread().start();

That is the shortest/easiest way I could think of.


You can refer to an example in my public repository as well. It's off-topic but it gets the concept.

Jay
  • 1,089
  • 12
  • 29