How to Schedule and Send Batch Emails Using Azure ACS and Spring Boot: Step-by-Step Guide

This diagram illustrates the end-to-end workflow of sending batch emails in a Spring Boot application:

  1. User Interaction: The admin/user configures the Quartz Scheduler with a trigger interval (e.g., every 60 seconds).
  2. Quartz Scheduler: The scheduler starts and triggers the batch job periodically.
  3. Spring Batch Processor: The batch job reads email recipients from the data source, processes them, and passes the recipients to the Email Service.
  4. Email Service: The Email Service sends the emails via Azure Communication Services (ACS).
  5. Azure Communication Services (ACS): ACS processes the emails and returns delivery status to the Email Service.
  6. Logging and Notifications: The Email Service logs the success or failure of email delivery, and the Batch Processor notifies the Scheduler of job completion.

This flow ensures a scheduled, automated, and efficient batch email sending process.


To set up Azure Communication Services (ACS) for sending batch emails using Spring Batch and Quartz Scheduler in a Spring Boot application, follow this comprehensive guide.


Overview

  • Azure Communication Services (ACS): Provides the email sending capability.
  • Spring Batch: Manages batch processing of email recipients.
  • Quartz Scheduler: Triggers the batch job on a schedule.

Step 1: Prerequisites

  1. Azure Communication Services Resource:

    • Create an ACS resource in the Azure Portal.
    • Enable the email service and configure a verified sender address.
    • Copy the connection string.
  2. Development Environment:

    • JDK 11+ installed.
    • Spring Boot setup with Maven or Gradle.

Step 2: Initialize Spring Boot Project

  1. Go to Spring Initializr.

  2. Configure the project:

    • Dependencies:
      • Spring Web
      • Spring Batch
      • Spring Boot Starter Quartz
      • Azure Communication Services Email SDK
  3. Download and import the project into your IDE.


Step 3: Add Dependencies

Add the following dependencies to your pom.xml.

<dependencies>
    <!-- Azure Communication Services Email SDK -->
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-communication-email</artifactId>
        <version>1.0.19</version>
    </dependency>

    <!-- Spring Batch -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>

    <!-- Quartz Scheduler -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
</dependencies>

Step 4: Configure Application Properties

Add the necessary configurations in application.properties.

# Azure Communication Services
azure.communication.connection-string=<Your-ACS-Connection-String>
email.from-address=<Your-Verified-Email>

Step 5: Create the Email Service

Implement a service to send emails using ACS.

import com.azure.communication.email.EmailClient;
import com.azure.communication.email.EmailClientBuilder;
import com.azure.communication.email.models.EmailAddress;
import com.azure.communication.email.models.EmailContent;
import com.azure.communication.email.models.EmailMessage;
import com.azure.communication.email.models.SendEmailResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmailService {

    private final EmailClient emailClient;
    private final String fromAddress;

    public EmailService(@Value("${azure.communication.connection-string}") String connectionString,
                        @Value("${email.from-address}") String fromAddress) {
        this.emailClient = new EmailClientBuilder()
                .connectionString(connectionString)
                .buildClient();
        this.fromAddress = fromAddress;
    }

    public void sendEmail(String recipient, String subject, String body) {
        try {
            EmailMessage message = new EmailMessage()
                    .setSenderAddress(fromAddress)
                    .setToRecipients(List.of(new EmailAddress().setEmail(recipient)))
                    .setContent(new EmailContent().setSubject(subject).setPlainText(body));

            SendEmailResult result = emailClient.send(message);
            System.out.println("Email sent to: " + recipient + ", Message ID: " + result.getMessageId());
        } catch (Exception e) {
            System.err.println("Failed to send email to: " + recipient + ", Error: " + e.getMessage());
        }
    }
}

Step 6: Configure Spring Batch

Create a Spring Batch configuration to process email recipients.

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.List;

@Configuration
@EnableBatchProcessing
public class BatchConfig {

    @Bean
    public ItemReader<String> emailReader() {
        return () -> Arrays.asList("user1@example.com", "user2@example.com", "user3@example.com").iterator();
    }

    @Bean
    public ItemProcessor<String, String> emailProcessor() {
        return recipient -> recipient; // No processing needed for this example
    }

    @Bean
    public ItemWriter<String> emailWriter(EmailService emailService) {
        return recipients -> recipients.forEach(recipient -> {
            emailService.sendEmail(recipient, "Batch Email", "This is a batch email sent via Spring Batch and ACS.");
        });
    }

    @Bean
    public Step emailStep(StepBuilderFactory stepBuilderFactory, ItemReader<String> reader,
                          ItemProcessor<String, String> processor, ItemWriter<String> writer) {
        return stepBuilderFactory.get("emailStep")
                .<String, String>chunk(10)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .build();
    }

    @Bean
    public Job emailJob(JobBuilderFactory jobBuilderFactory, Step emailStep) {
        return jobBuilderFactory.get("emailJob")
                .start(emailStep)
                .build();
    }
}

Step 7: Configure Quartz Scheduler

Create a Quartz job to trigger the batch job.

import org.quartz.*;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class QuartzEmailJob implements Job {

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job emailJob;

    @Override
    public void execute(JobExecutionContext context) {
        try {
            jobLauncher.run(emailJob, new JobParameters());
        } catch (Exception e) {
            System.err.println("Failed to execute batch job: " + e.getMessage());
        }
    }
}

Step 8: Configure Quartz Triggers

Set up Quartz to trigger the email job.

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail quartzEmailJobDetail() {
        return JobBuilder.newJob(QuartzEmailJob.class)
                .withIdentity("quartzEmailJob")
                .storeDurably()
                .build();
    }

    @Bean
    public Trigger quartzEmailJobTrigger() {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(60) // Trigger every 60 seconds
                .repeatForever();

        return TriggerBuilder.newTrigger()
                .forJob(quartzEmailJobDetail())
                .withIdentity("quartzEmailTrigger")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

Step 9: Run the Application

  1. Start the Spring Boot application.
  2. The Quartz Scheduler will trigger the Spring Batch job every 60 seconds.

Testing

  • Verify that emails are sent to recipients in the list.
  • Check the logs for success or failure messages.

Unlock Your Microservices Mastery for Only $9!

Get your copy now for just $9! and start building resilient and scalable microservices with the help of Microservices with Spring Boot 3 and Spring Cloud.


Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete