Design and write a Micro Service responsible of Asynchronous sending of Emails with attachments. It should support retry in case of SMTP server connection failure. Implement a consumer who listen and react to a topic in front of the service. To solve this problem please use Kafka and Consumer-API.
We have used JavaMailSender
and MimeMessage
to send the emails with attachments.
For SMTP server configuration, we can either use Gmail or any other free SMTP server.
Max retry attempts can be configured using constant: ResilientValue.MAX_RETRY
By default Gmail account is highly secured. When we use gmail smtp from non gmail tool, email is blocked. To test in our local environment, make your gmail account less secure as
- Login to Gmail.
- Access the URL as https://www.google.com/settings/security/lesssecureapps
- Select "Turn on"
If using mailjet, then add the sender address and verify it. Also add the sender address (setFrom) in Java mailClient
Configuration for both Gmail and Mailjet SMTP server is similar. Below is a snippet containing the sample configuration via application.yaml
spring:
mail:
host: <SMTP-server>
port: 587
username: <user-name>
password: <password>
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
starttls:
enable: true
Use this handy quick start guide to setup kafka. Below are few commands to run and create topics.
zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties
kafka-server-start /usr/local/etc/kafka/server.properties
kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
kafka-topics --list --zookeeper localhost:2181
kafka-topics --delete --zookeeper localhost:2181 --topic <topic-name>
Before running the micro-service, please make sure to update application.yaml
with working SMTP host, username and password values.
Configure the kafka topic using property kafka.mail.topic
in application.yaml
Run below command to start the program.
mvn clean package spring-boot:run
By default, the kafka
profile is active, which means you have to setup the kafka and zookeeper and update the application.yaml
file before running the application.
But if you want to run the application without kafka
, use below command.
mvn clean package spring-boot:run -Dspring-boot.run.profiles=default
There are three ways to use this microservice.
/v1/group/mail/sent
path has been exposed that take Email
object as a post request body.
Below curl request can be used to send the email directly via this exposed rest endpoint
curl --location --request POST 'localhost:8080/v1/group/mail/sent' \
--header 'Content-Type: application/json' \
--data-raw '{
"to" : "***@gmail.com",
"from" : "***@gmail.com",
"subject" : "Demo Test Email with Attachment",
"content" : "<h1>Testing from Spring Boot</h1>",
"isHtmlContent" : true,
"attachmentUriList" : [
"/tmp/test1.yml",
"/tmp/test2.JPG"
]
}'
/v1/group/mail/publish
path has been exposed that take Email
object as a post request body. This endpoint redirects the data to a kafka producer that sends it to topic mailjet
Below curl request can be used to send the email directly via this exposed rest endpoint
curl --location --request POST 'localhost:8080/v1/group/mail/publish' \
--header 'Content-Type: application/json' \
--data-raw '{
"to" : "***@gmail.com",
"from" : "***@gmail.com",
"subject" : "Demo Test Email with Attachment",
"content" : "<h1>Testing from Spring Boot</h1>",
"isHtmlContent" : true,
"attachmentUriList" : [
"/tmp/test1.yml",
"/tmp/test2.JPG"
]
}'
You can also use the kafka producer console to send the data directly to a topic. Configure that topic in Consumer.java
class and the consumer will listen to it.
kafka-console-producer --broker-list localhost:9092 --topic <topic-name>
Below json can be used to send the request via kafka Producer console.
{"to":"***@gmail.com","from":"***@gmail.com","subject":"Demo Test Email with Attachment","content":"<h1>Testing from Spring Boot</h1>","isHtmlContent":true,"attachmentUriList":["/tmp/test1.yml","/tmp/test2.JPG"]}