Backend Development 12 min read

Reliable Email Sending with RabbitMQ and Spring Boot: Architecture, Implementation, and Testing

This article presents a complete Spring Boot solution for sending emails via RabbitMQ, covering message confirmation, consumer idempotency, retry mechanisms, manual acknowledgments, configuration details, code implementation, testing procedures, and an optional dynamic‑proxy extension for clean business logic.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Reliable Email Sending with RabbitMQ and Spring Boot: Architecture, Implementation, and Testing

The tutorial begins with an overall flow diagram that outlines the key RabbitMQ concepts used: publisher confirms, consumer acknowledgments, message redelivery, and idempotent consumption.

Implementation steps include obtaining a 163.com mail authorization code, creating a mail‑sending utility ( MailUtil ), configuring RabbitMQ ( RabbitConfig ), and defining the producer ( TestServiceImpl ) and consumer ( MailConsumer ) components.

Key configuration snippets :

spring.rabbitmq.host=localhost
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.mail.host=smtp.163.com

The MailUtil class builds a SimpleMailMessage and sends it via JavaMailSender , logging success or failure. The producer generates a UUID message ID, stores a MsgLog record, and sends the message with CorrelationData for tracking.

The consumer retrieves the message, checks the MsgLog status to ensure idempotency, attempts to send the email, updates the log status, and performs manual ACK ( channel.basicAck ) on success or NACK ( channel.basicNack ) on failure, triggering redelivery.

A scheduled task ( ResendMsg ) runs every 30 seconds, queries messages that are still in "delivering" state, increments retry counters, and re‑sends them up to three times before marking them as failed.

Testing includes normal flow verification (sending request, checking logs, database records, and email receipt), as well as failure scenarios: exchange‑to‑exchange routing failure, exchange‑to‑queue routing failure, missing manual ACK, consumer exceptions, and retry task execution.

The article concludes with an optional dynamic‑proxy approach to abstract idempotency checks and ACK handling, allowing business logic (e.g., mailUtil.send(mail) ) to remain clean.

backendSpring BootRabbitMQIdempotencyEmailAckMessage Retry
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.