SMTP Configuration

SMTP (Simple Mail Transfer Protocol) is the standard protocol applications use to send email through a mail server. Spring Boot connects to an SMTP server using the spring-boot-starter-mail dependency and spring.mail.* properties. It auto-creates a JavaMailSender bean, so you can send emails without writing any connection code. It is used for registration confirmations, password resets, notifications, and reports.

Features

  • Auto-configuration of JavaMailSender from application.properties
  • Simple text emails with SimpleMailMessage
  • Support for TLS/SSL secured connections (STARTTLS on port 587)
  • Timeout settings for connection, read, and write
  • Works with any provider: Gmail, Outlook, Amazon SES, Mailtrap, or a company mail server
  • Easy to inject into any service class

Hands-on Experiment: Creating a spring boot application to understand how Spring Boot connects to an SMTP server for sending application emails.

The following steps are involved in developing this hands-on experiment.

Step 1: Generate the Project

Step 2: Project Structure

Step 3: pom.xml

Step 4: application.properties

Step 5: Create Entity Class

Step 6: Create Repository Interface

Step 7: Create Service Class

Step 8: Create Controller Class

Step 9: Main Application Class

Step 10: Run the Main Application Class

Step 1: Configure the Project on Spring Initializr

Go to start.spring.io and set:

  • Project: Maven
  • Language: Java
  • Spring Boot version: 3.2.x
  • Group: com.example
  • Artifact: smtpdemo
  • Name: smtpdemo
  • Package name: com.example.smtpdemo
  • Packaging: Jar
  • Java: 17
  • Dependencies: Spring Web, Spring Data JPA, MySQL Driver, Java Mail Sender.

Click Generate to download the ZIP, then extract and import it into your IDE as a Maven project.

Step 2: Generated Project Structure

Step 3: Explore pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>student-smtp-demo</artifactId>
    <version>1.0.0</version>
    <name>student-smtp-demo</name>
    <description>SMTP Configuration - Student registration confirmation email</description>

    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
       <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Step 4: application.properties

spring.application.name=student-smtp-demo

# ---------- MySQL ----------
# Create the database first:  CREATE DATABASE student_smtp_db;
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# ---------- SMTP (Gmail example) ----------
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=your-email@gmail.com
# Use a 16-character Gmail App Password (NOT your normal password)
spring.mail.password=your-app-password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000

# ---------- Custom ----------
app.mail.from=your-email@gmail.com

Step 5: Create Entity Class

package com.example.smtpdemo.entity;

import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "students")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false, unique = true)
    private String email;

    private String course;

    private LocalDateTime registeredAt;

    // SENT or FAILED
    private String emailStatus;

    public Student() {
    }

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public String getCourse() { return course; }
    public void setCourse(String course) { this.course = course; }

    public LocalDateTime getRegisteredAt() { return registeredAt; }
    public void setRegisteredAt(LocalDateTime registeredAt) { this.registeredAt = registeredAt; }

    public String getEmailStatus() { return emailStatus; }
    public void setEmailStatus(String emailStatus) { this.emailStatus = emailStatus; }
}

Step 6: Create below Repository Interface

package com.example.smtpdemo.repository;

import com.example.smtpdemo.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {

    boolean existsByEmail(String email);
}

Step 7: Create below Service class

package com.example.smtpdemo.service;

import com.example.smtpdemo.entity.Student;
import com.example.smtpdemo.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class StudentService {

    private final StudentRepository studentRepository;
    private final JavaMailSender mailSender;   // auto-configured from spring.mail.* properties

    @Value("${app.mail.from}")
    private String fromAddress;

    public StudentService(StudentRepository studentRepository, JavaMailSender mailSender) {
        this.studentRepository = studentRepository;
        this.mailSender = mailSender;
    }

    public Student register(Student student) {
        if (studentRepository.existsByEmail(student.getEmail())) {
            throw new IllegalArgumentException("Email already registered: " + student.getEmail());
        }

        student.setRegisteredAt(LocalDateTime.now());
        student.setEmailStatus("PENDING");
        Student saved = studentRepository.save(student);

        // Registration succeeds even if the mail server is down
        try {
            sendConfirmation(saved);
            saved.setEmailStatus("SENT");
        } catch (Exception ex) {
            System.err.println("Mail failed: " + ex.getMessage());
            saved.setEmailStatus("FAILED");
        }
        return studentRepository.save(saved);
    }

    public Student resendConfirmation(Long id) {
        Student student = studentRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Student not found: " + id));
        try {
            sendConfirmation(student);
            student.setEmailStatus("SENT");
        } catch (Exception ex) {
            System.err.println("Mail failed: " + ex.getMessage());
            student.setEmailStatus("FAILED");
        }
        return studentRepository.save(student);
    }

    public List<Student> getAll() {
        return studentRepository.findAll();
    }

    private void sendConfirmation(Student student) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(fromAddress);
        message.setTo(student.getEmail());
        message.setSubject("Registration Confirmation");
        message.setText("Hello " + student.getName() + ",\n\n"
                + "You have been registered successfully for the course: " + student.getCourse() + ".\n"
                + "Your Student ID is " + student.getId() + ".\n\n"
                + "Regards,\nStudent Admissions Team");
        mailSender.send(message);
    }
}

Step 8: Create Controller class

package com.example.smtpdemo.controller;

import com.example.smtpdemo.entity.Student;
import com.example.smtpdemo.service.StudentService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/students")
public class StudentController {

    private final StudentService studentService;

    public StudentController(StudentService studentService) {
        this.studentService = studentService;
    }

    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody Student student) {
        try {
            return ResponseEntity.status(HttpStatus.CREATED).body(studentService.register(student));
        } catch (IllegalArgumentException ex) {
            return ResponseEntity.badRequest().body(Map.of("error", ex.getMessage()));
        }
    }

    @PostMapping("/{id}/resend-email")
    public ResponseEntity<?> resend(@PathVariable Long id) {
        try {
            return ResponseEntity.ok(studentService.resendConfirmation(id));
        } catch (IllegalArgumentException ex) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("error", ex.getMessage()));
        }
    }

    @GetMapping
    public List<Student> getAll() {
        return studentService.getAll();
    }
}

Step 9: Main Application

package com.example.smtpdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SmtpDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SmtpDemoApplication.class, args);
    }
}

Step 10: Run the SmtpDemoApplication

Scroll to Top