Sending Emails is the most common task for most backend applications. Java provides Java Mail API - a platform and protocol-independent framework to build mail and messaging applications. You can find documentation here.
In this guide, you will get simple steps to set up JavaMail in your Java Project + implement JavaMail API to build and send emails on SMTP protocol and use the tool MailHog to test that emails are gone in a Mail Inbox.
Requirements
- Basic knowledge on Docker
- Basic knowledge on Java
- These Maven dependencies ππ½
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Set the email properties
To send an email, you should define some SMTP properties in the application.properties, it is usually a good practice to set config and properties values in the application.properties file.
spring.mail.host=localhost
spring.mail.port=1025
spring.mail.username=user123
spring.mail.password=admin
After that, you should retrieve all those properties in a POJO
@Getter
@Setter
@Component
@Validated
@ConfigurationProperties(prefix = "spring.mail")
public class AppConfigs {
@NotNull
private String host;
@NotNull
private int port;
@NotNull
private String username;
@NotNull
private String password;
}
@ConfigurationProperties
classes available in Spring Boot, but the accessors (getters/setters) of the class itself are not meant to be used directly.Finally, in a Mailservice class we can set properties for sending email
private Properties getProperties() {
Properties properties = new Properties();
properties.put("mail.smtp.host", appConfigs.getHost());
properties.put("mail.smtp.port", appConfigs.getPort());
properties.put("mail.user", appConfigs.getPort());
properties.put("mail.password", appConfigs.getPort());
return properties;
}
Set the email headers
Now you can define the email headers (sender, receiver, subject and date)
MimeMessage message = new MimeMessage(session);
message.setFrom("sender-test@example.com");
message.setRecipients(RecipientType.TO, "receiver-test@example.com");
message.setSubject("Testing Javax Mail and MailHog");
message.setSentDate(new Date());
Set the email body
For this tutorial, we will use an HTML email template, which is located in resources/static/mail
MimeBodyPart messageBodyPart = new MimeBodyPart();
File htmlFile = getFile("classpath:static/mail/content.html");
String htmlFileContent = new String(readAllBytes(htmlFile.toPath()));
messageBodyPart.setContent(htmlFileContent, "text/html");
Set the image body
To use an image in the body of your mail, you can load an image from your disk and print it in email
MimeBodyPart imageBodyPart = new MimeBodyPart();
File attachmentFile = getFile("classpath:static/attachments/email-logo.png");
imageBodyPart.setHeader("Content-Id","<logoImage>");
imageBodyPart.setDisposition(MimeBodyPart.INLINE);
imageBodyPart.attachFile(attachmentFile);
Set the mail sender
Once all the parts of the mail have been created, you can assemble them with the class Multipart, then send the mail
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
multipart.addBodyPart(imageBodyPart);
message.setContent(multipart);
send(message);
The whole MailService class will look like this
@Service
@RequiredArgsConstructor
public class MailService {
private final AppConfigs appConfigs;
public void sendSimpleMail() {
Properties properties = getProperties();
Session session = Session.getInstance(properties);
try {
MimeMessage message = new MimeMessage(session);
message.setFrom("sender-test@example.com");
message.setRecipients(RecipientType.TO, "receiver-test@example.com");
message.setSubject("Testing Javax Mail and MailHog");
message.setSentDate(new Date());
MimeBodyPart messageBodyPart = new MimeBodyPart();
File htmlFile = getFile("classpath:static/mail/content.html");
String htmlFileContent = new String(readAllBytes(htmlFile.toPath()));
messageBodyPart.setContent(htmlFileContent, "text/html");
MimeBodyPart imageBodyPart = new MimeBodyPart();
File attachmentFile = getFile("classpath:static/attachments/email-logo.png");
imageBodyPart.setHeader("Content-Id","<logoImage>");
imageBodyPart.setDisposition(MimeBodyPart.INLINE);
imageBodyPart.attachFile(attachmentFile);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
multipart.addBodyPart(imageBodyPart);
message.setContent(multipart);
send(message);
}catch (Exception exception) {
System.out.println("Sending Email failed, error : " + exception.getMessage());
}
}
private Properties getProperties() {
Properties properties = new Properties();
properties.put("mail.smtp.host", appConfigs.getHost());
properties.put("mail.smtp.port", appConfigs.getPort());
properties.put("mail.user", appConfigs.getPort());
properties.put("mail.password", appConfigs.getPort());
return properties;
}
}
The part where we set the content ID for the image is bind with the src element in the HTML content of our email template.
You can get this line here.
Email reception with MailHog
To be able to test that email will actually go into the client inbox, we will use a tool called Mailhog.
It is an email testing tool for developers which helps you view messages in the web UI, or retrieve them with the JSON API and optionally release messages to real SMTP servers for delivery
Now that we have configured our Mail Service class we can set up our local server for testing that email is sent. First of all you should create a env file
Β where you can store all the config for the Mailhog local server.
{
"server name": {
"name": "mailhog",
"host": "localhost",
"port": "1025",
"username": "user123",
"password": "admin",
"mechanism": "PLAIN"
}
}
After that, we can modify a Dockerfile inspired by Mailhog documentation
# MailHog Dockerfile
FROM golang:1.18-alpine as builder
# Install MailHog:
RUN apk --no-cache add --virtual build-dependencies \\
git \\
&& mkdir -p /root/gocode \\
&& export GOPATH=/root/gocode \\
&& go install github.com/mailhog/MailHog@latest
FROM alpine:3
RUN adduser -D -u 1000 mailhog
COPY --from=builder /root/gocode/bin/MailHog /usr/local/bin/
USER mailhog
WORKDIR /home/mailhog
COPY env.smtp .
ENTRYPOINT MailHog -outgoing-smtp ./env.smtp
# Expose the SMTP and HTTP ports:
EXPOSE 1025 8025
COPY env.smtp .
part is necessary to run Mailhog image as an entrypoint with option for mailhog CLI.Now you can build your Mailhog local image with this docker command in the root directory of your project
docker build --no-cache . -t mailhog-local
Then run the Image in a brand-new container with this command
docker run -d --name mailhog-local -p 1025:1025 -p 8025:8025 mailhog-local
Once the container is up, you can access your local instance of Mailhog via localhost:8085
Now we can test email sending via a simple spring boot controller
import com.example.demo.service.MailService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController("/mail")
@RequiredArgsConstructor
public class MailController {
private final MailService mailService;
@GetMapping("/send-simple-mail")
void sendMail() {
mailService.sendSimpleMail();
}
}
To test our application, we can start our spring boot server with this command
mvn spring-boot:run
Once the app server is up, we can test the URL with Curl
curl localhost:8080/send-simple-mail
And we get the result in our Mailhog UI.
You can found the entire code for this tutorial on my GitHub.
π. Similar posts
Simplifying Layouts With React Fragments
18 Jan 2025
Stop Installing Node Modules on Your Docker Host - Install Them in the Container Instead
14 Jan 2025
An Easy to Understand React Component Introduction for Beginners
14 Jan 2025