1. Introduction
During this exercise we will use the Spring Boot Starter for sending email from our application.
2. Background info
Spring Boot provides an abstraction for sending email using the JavaMailSender interface. When you add the spring-boot-starter-mail dependency and configure spring.mail.host, Spring Boot auto-configures a JavaMailSender bean for you.
-
MailSender— top-level interface providing basic functionality for sending simple emails -
JavaMailSender— extendsMailSender, supports MIME messages (attachments, HTML, etc.) -
JavaMailSenderImpl— the implementation class, auto-configured by Spring Boot -
SimpleMailMessage— a simple value object for plain-text email (to, from, cc, subject, text) -
MimeMessageHelper— helper class for creating MIME messages with attachments, inline images, and HTML content
Since Spring Boot 3+, the underlying library is Jakarta Mail (the jakarta.mail package), which is the successor to the old JavaMail API (javax.mail). Your application code uses Spring’s abstractions (JavaMailSender, SimpleMailMessage), so this change is transparent.
|
3. Maven dependency
Add the following to your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
4. Mail server properties
Configure the SMTP server in your application.properties:
4.1. Gmail SMTP
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your.email@gmail.com
spring.mail.password=your-app-password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
# Recommended: set timeouts to avoid blocking threads on an unresponsive mail server
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000
| Do not use your regular Gmail password. Google requires an App Password for third-party applications. To generate one: go to your Google Account → Security → 2-Step Verification → App passwords. See Google App Passwords for instructions. |
4.2. Local mail server (e.g. Postfix on Linux)
spring.mail.host=localhost
spring.mail.port=25
spring.mail.username=your-username
spring.mail.password=your-password
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.starttls.enable=false
4.3. Using a fake SMTP server for testing (recommended for training)
If you don’t want to use a real mail server during the training, you can use a tool like MailHog or Mailpit which captures all outgoing emails without actually delivering them:
docker run -d -p 1025:1025 -p 8025:8025 axllent/mailpit
Then configure:
spring.mail.host=localhost
spring.mail.port=1025
Open http://localhost:8025 in your browser to see all captured emails.
| This is the safest approach for a training environment — no risk of accidentally sending real emails. |
5. Sending email
5.1. Step 1: Create the EmailService
package com.acme.carapp.service;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
@Service
public class EmailService {
private final JavaMailSender mailSender;
public EmailService(JavaMailSender mailSender) { (1)
this.mailSender = mailSender;
}
public void sendSimpleMessage(String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
}
}
| 1 | We use constructor injection (recommended) instead of @Autowired on the field. |
5.2. Step 2: Create the EmailController
Add a REST controller which accepts to, subject, and text parameters:
package com.acme.carapp.api;
import com.acme.carapp.service.EmailService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("api/email")
public class EmailController {
private final EmailService emailService;
public EmailController(EmailService emailService) {
this.emailService = emailService;
}
@PostMapping
public ResponseEntity<String> sendEmail(
@RequestParam String to,
@RequestParam String subject,
@RequestParam String text) {
emailService.sendSimpleMessage(to, subject, text);
return ResponseEntity.ok("Email sent successfully");
}
}
5.3. Step 3: Test with Postman
Send a POST request to http://localhost:8080/api/email with the following parameters:
-
subject= Hello from CarApp -
text= This is a test email from our Spring Boot training!
If you’re using Mailpit, check http://localhost:8025 to see the captured email.
6. Done
For this part of the exercise you are done regarding using the spring-boot-starter-mail.
7. Continuation (when time permits)
7.1. Sending emails with attachments
For more complex emails (attachments, HTML content), use MimeMessageHelper:
public void sendMessageWithAttachment(String to, String subject, String text, String pathToAttachment) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true); (1)
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file = new FileSystemResource(new File(pathToAttachment));
helper.addAttachment(file.getFilename(), file);
mailSender.send(message);
} catch (MessagingException e) {
throw new RuntimeException("Failed to send email with attachment", e);
}
}
| 1 | The true parameter enables multipart mode, which is required for attachments. |
7.2. Sending HTML emails
public void sendHtmlMessage(String to, String subject, String htmlContent) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent, true); (1)
mailSender.send(message);
} catch (MessagingException e) {
throw new RuntimeException("Failed to send HTML email", e);
}
}
| 1 | The second true parameter tells Spring that the text is HTML. |
7.3. Simple email template
You can define a template bean in your configuration:
@Bean
public SimpleMailMessage emailTemplate() {
SimpleMailMessage message = new SimpleMailMessage();
message.setText("Hello %s,\n\nYour car '%s' has been successfully registered.\n\nKind regards,\nCarApp");
return message;
}
And use it in your service:
@Autowired
private SimpleMailMessage emailTemplate;
public void sendRegistrationEmail(String to, String name, String carBrand) {
String text = String.format(emailTemplate.getText(), name, carBrand);
sendSimpleMessage(to, "Car Registration Confirmation", text);
}
8. Handling send errors
JavaMailSender may throw a MailException (or its subclasses like MailSendException) when sending fails. However, be aware that a successful send does not guarantee delivery — the SMTP server may accept the message but still fail to deliver it (e.g. invalid recipient address). In that case, you typically receive a "delivery failed" bounce email rather than an exception.
| For production applications, consider wrapping your email sending in a try-catch and logging failures. For critical emails (password resets, order confirmations), consider using a transactional outbox pattern or a dedicated email delivery service (e.g. SendGrid, Amazon SES, Mailgun). |
9. Further reading
Sending Email - Spring Boot Reference |
|
Guide to Spring Email - Baeldung |
|
Google App Passwords |
|
Mailpit - fake SMTP server |