SpringBoot Email Sending with @Async Optimization
276 words
1 minute
SpringBoot Email Sending with @Async Optimization
SpringBoot Email Sending with @Async Optimization
Basic Configuration
1. Add the Dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId></dependency>2. Configure Mail Properties
spring: mail: password: your-auth-code host: smtp.163.comThe password field requires an authorization code, not your email login password. For 163 mail, enable POP3/SMTP/IMAP in settings and generate an auth code.
3. Send a Simple Email
@RestController@RequiredArgsConstructorpublic class EmailController {
private final JavaMailSender javaMailSender;
@GetMapping("/send-email") public String sendEmail(String email) { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(email); message.setSubject("Verification Code"); message.setText("Your code is: 123456"); javaMailSender.send(message); return "ok"; }}Async Sending with @Async
Synchronous email sending blocks the request thread. For high-concurrency scenarios, async is recommended.
1. Enable Async Support
@SpringBootApplication@EnableAsyncpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}2. Async Email Service
@Component@Slf4jpublic class EmailService {
@Autowired private JavaMailSender javaMailSender;
@Autowired private StringRedisTemplate stringRedisTemplate;
@Async public void sendVerificationCode(String email) { String code = UUID.randomUUID().toString().substring(0, 6); SimpleMailMessage message = new SimpleMailMessage(); message.setTo(email); message.setSubject("Verification Code"); message.setText(code);
stringRedisTemplate.boundValueOps("code:" + email) .set(code, 5, TimeUnit.MINUTES); javaMailSender.send(message); log.info("Verification code sent to: {}", email); }}3. Custom Thread Pool
The default async thread pool has a core pool size of 8. Adjust it as needed:
spring: task: execution: pool: core-size: 50Or via Java configuration:
@Beanpublic ThreadPoolTaskExecutor threadPoolExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(20); executor.setMaxPoolSize(50); executor.setQueueCapacity(200); executor.setThreadNamePrefix("mail-executor-"); executor.initialize(); return executor;}Common @Async Pitfalls
@Async won’t work in these cases:
- The method is not
public - Return type is not
voidorFuture - The method is
static - Spring cannot scan the class (missing
@Component/@Serviceetc.) - Caller and callee are in the same class — Spring AOP proxies can’t intercept internal calls
- Creating the object with
newinstead of dependency injection - Adding
@Transactionaldirectly on an@Asyncmethod — put@Transactionalon the called method instead
Reference: https://blog.csdn.net/u011413452/article/details/124844941
Support & Share
If this article helped you, please share or support!
SpringBoot Email Sending with @Async Optimization
https://blog.zinzin.cc/posts/springboot-email-en/Related PostsSmart
1
Send SMS via Tencent Cloud API with Spring Boot
JavaA progressive guide from raw API debugging to a clean Spring Boot utility class, covering configuration property binding and static utility design.
2
Request Wildcard SSL Certificates with acme.sh
DevOpsGet free Let's Encrypt wildcard certificates via acme.sh + Cloudflare DNS API with automatic renewal.
3
Deploy a Nacos Cluster with Docker
DevOpsA complete guide to deploying a 3-node Nacos 2.2 cluster with Docker, using MySQL for persistence and Nginx for load balancing.
4
Switch Java (JDK) Versions Freely with Scoop
Dev ToolsInstall multiple JDK versions on Windows using Scoop package manager and switch between them with a single command — no more manual environment variable tweaking.
5
2025 Year in Review
Annual ReviewReflections on 2025 — covering work, learning, health, books, games, anime, and travel.
Random PostsRandom













