In this tutorial, you’ll learn how to send emails asynchronously in Spring Boot using JavaMailSender and the @Async annotation.

This is useful for sending OTPs, registration confirmations, notifications, or password reset emails — all without blocking your main API thread.


1. Add Mail Dependencies

In your pom.xml, include the Spring Boot mail starter dependency:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

2. Configure SMTP Settings

Add your mail configuration in application.properties (or application.yml):


spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=test@gmail.com
spring.mail.password=YOUR_APP_PASSWORD
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

Note: For Gmail, you must use an App Password (not your regular Gmail password). You can create it from your Google Account → Security → App Passwords.


3. Enable Asynchronous Execution

To make email sending asynchronous (non-blocking), enable async processing in your main Spring Boot application class:


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class EmailApp {
    public static void main(String[] args) {
        SpringApplication.run(EmailApp.class, args);
    }
}

4. Create Email Service

Now create a service class that sends emails asynchronously using @Async:


package com.diagnotoutil.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class EmailService {

    @Autowired
    private JavaMailSender mailSender;

    @Async
    public void sendEmail(String to, String subject, String body) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(to);
        message.setSubject(subject);
        message.setText(body);
        message.setFrom("test@gmail.com");

        mailSender.send(message);
    }
}

5. Test Email Sending

You can create a simple REST controller to test sending emails:


@RestController
@RequestMapping("/api/mail")
public class MailController {

    @Autowired
    private EmailService emailService;

    @PostMapping("/send")
    public String sendMail(@RequestParam String to,
                           @RequestParam String subject,
                           @RequestParam String body) {
        emailService.sendEmail(to, subject, body);
        return "Email sent successfully (asynchronously)!";
    }
}

6. How It Works

  • @Async runs the sendEmail() method in a separate background thread.
  • The API immediately returns a response — the email sending happens in the background.
  • This keeps your app responsive and improves user experience.

7. Example Output

When you hit the endpoint:


POST http://localhost:8080/api/mail/send?to=test@example.com&subject=Hello&body=Welcome to Diagnoto!

Your console will show:


✅ Email sent successfully

And your recipient will receive the email instantly.


8. Common Troubleshooting Tips

  • Use an App Password if using Gmail SMTP (not your normal password).
  • Ensure “Less secure apps” is disabled — App Passwords are the secure replacement.
  • If you get a MailAuthenticationException, double-check your username, password, and port (587).

Conclusion

That’s it! 🎉 You’ve learned how to send emails asynchronously in Spring Boot using JavaMailSender and @Async.

This technique helps improve performance and scalability — especially for real-world use cases like user registration, password resets, and notification systems.


Next Step: You can enhance this by using MimeMessageHelper for HTML emails or adding attachments.