Guides
Last updated
July 25, 2025

5 Ways to Implement Email Validation in Spring Boot

Nicolas Rios
Nicolas Rios
Table of Contents:
ON THIS PAGE
Get your free
email validation
 API key now
stars rating
4.8 from 1,863 votes
See why the best developers build on Abstract
START FOR FREE
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
No credit card required

Validating email addresses in Spring Boot is fundamental for data quality and user account integrity. We will explore five different approaches, complete with code examples, to handle this task. We will also examine the pitfalls of these traditional methods and show how Abstract API offers a more robust solution.

How to Implement Email Validation in Spring Boot

Here are four common methods to validate email addresses in a Spring Boot application. Each approach uses different libraries and techniques to check for syntactically correct email addresses.

Hibernate-Validator's @Email Annotation

The simplest method uses the built-in @Email annotation. Add the spring-boot-starter-validation dependency to your project, which pulls in Hibernate-Validator. You can then apply the @Email annotation directly to a field within a Data Transfer Object (DTO).

Spring Boot automatically configures a MethodValidationPostProcessor. This bean ensures the constraint check occurs whenever the DTO is bound from a request or when a method marked with @Validated is called. The default implementation uses a permissive regular expression that accepts domains without a top-level domain, as some developers note.

public record SignupCmd(
    @Email(message = "Address syntax is wrong")
    String email
) {}

A Hardened Annotation with @Email and a Pattern

To enforce a stricter format, you can enhance the default @Email annotation with a regular expression. This ensures the domain part of the email contains at least one dot, which rejects addresses like "user@localhost". There are two ways to accomplish this.

With Hibernate-Validator 6.x or newer, you can override the default regex directly inside the annotation. Alternatively, you can create a custom composite annotation that combines @Email with a @Pattern check. This approach, also found on Stack Overflow, keeps the built-in local-part validation but adds the top-level domain guard.

// Option A: Override the default regex
@Email(regexp = ".+@.+\\..+", message = "Missing top-level domain")
String email;
// Option B: Compose a custom annotation
@Email
@Pattern(regexp = ".+@.+\\..+")
@ReportAsSingleViolation
public @interface StrictEmail {}

Custom ConstraintValidator with Apache Commons-Validator

For more advanced validation logic, you can delegate to the Apache Commons-Validator library. This requires the commons-validator dependency. The process involves the creation of a custom annotation and a corresponding validator class, a common pattern in Java validation.

First, define a new annotation, for example @ValidEmail, and link it to a validator class. This class implements Spring's ConstraintValidator interface. Inside the isValid method, you delegate the check to an instance of Apache's EmailValidator. The library follows RFC 822 specifications for its checks.

// 1. The custom annotation
@Target({FIELD})@Retention(RUNTIME)
@Constraint(validatedBy = CommonsEmailValidator.class)
public @interface ValidEmail {    
  String message() default "Bad email";    
  Class<?>[] groups() default {};    
  Class<? extends Payload>[] payload() default {};
}

// 2. The validator implementation
public class CommonsEmailValidator implements ConstraintValidator<ValidEmail, String> {    
  private static final EmailValidator DELEGATE = EmailValidator.getInstance(false);    

  public boolean isValid(String value, ConstraintValidatorContext ctx) {        
    return value == null || DELEGATE.isValid(value);    
  }
}

Active MX Record Lookup

This runtime technique verifies that a domain is configured to receive mail. The process first checks the email's syntax with Java's InternetAddress class. If the syntax is valid, it performs a DNS lookup for the domain's Mail Exchange (MX) records.

The presence of at least one MX record indicates the domain can accept email. This logic is typically encapsulated within a Spring @Service. Because this involves a network call, it is best to wrap the operation in a CompletableFuture or a Reactor type to avoid block of the request thread. Caches also help reduce redundant DNS queries.

// Example DNS lookup logic
// Assumes 'domain' is extracted from the email address
DirContext ctx = new InitialDirContext(env); // 'env' holds JNDI environment properties
Attributes mx = ctx.getAttributes("dns:/" + domain, new String[]{"MX"});
boolean hasMxRecord = mx.size() > 0;

Challenges with Traditional Email Validation

While these methods provide basic syntax checks, they introduce several problems. These issues range from overly permissive rules to an inability to handle international addresses or confirm an inbox actually exists.

  • The default @Email annotation from Hibernate-Validator accepts addresses without a top-level domain. Developers often add extra @Pattern rules to compensate, which creates brittle and complex validation logic that is hard to maintain.
  • Standard validators like @Email and Apache Commons-Validator are ASCII-centric. They fail to parse internationalized email addresses that contain non-Latin characters, which limits a service's ability to support a global user base without extra libraries.
  • Attempts to cover all RFC-legal edge cases with a custom regex often fail. These complex patterns become unreadable and introduce the risk of Regular Expression Denial of Service (ReDoS) vulnerabilities, which can cripple an application.
  • Syntax validation, even with an MX record lookup, cannot confirm an inbox exists. An address may pass all checks but belong to a disposable domain or a spam-filtered mailbox, which makes the validation unreliable for deliverability.

Validate Emails with Abstract API
Stop invalid sign-ups and improve data accuracy in your Spring Boot application with email validation.
Get started for free

How Abstract API Handles Email Validation in Spring Boot

Abstract API addresses the core weaknesses of traditional validation methods through a multi-layered verification process that goes far beyond simple pattern matches.

  • The service combines multiple checks into one API call. These include syntax validation, autocorrection, MX and SMTP lookups, and checks for disposable, role-based, or free domains.
  • A clear deliverability field allows you to decide immediately whether to accept an email, so you avoid delays from hard bounces.
  • It offloads maintenance. The Abstract team keeps its disposable domain lists and validation rules current, so your application code remains static as rules evolve.
  • The service provides operational guarantees like a 99.99% SLA. You do not need to run your own probes or manage network issues because integration is a simple HTTPS call.
  • It uses a stable, versioned JSON structure. This structure maps easily to a record or DTO in your Spring application for type-safe data transfer.

How to Set Up Abstract API in Your Project

Once you know Abstract’s capabilities, you can add its email validation API to your project with ease.

  • First, add the reactive WebClient dependency to your project. For a Gradle project, you would add implementation("org.springframework.boot:spring-boot-starter-webflux").
  • Next, place your API key in the application.yml configuration file. This action separates your credentials from your code.
abstract: 
  email:    
    api-key: YOUR_KEY

Sample Email Validation Implementation with Abstract API

The implementation requires a service to call the API and a data transfer object (DTO) to hold the response. You can then inject this service into a custom Spring ConstraintValidator to check emails during the validation lifecycle. The code below shows all the necessary components.

// 1. DTO to map the JSON response
public record AbstractEmailResponse(    
  String email,     
  String deliverability,    
  float quality_score,     
  IsValid is_valid_format,     
  IsFlag is_disposable_email,    
  IsFlag is_role_email,     
  IsFlag is_free_email,     
  IsFlag is_catchall_email,    
  IsFlag is_mx_found,     
  IsFlag is_smtp_valid,     
  String autocorrect
) {}
public record IsValid(boolean value, String text) {}
public record IsFlag(boolean value, String text) {}

// 2. WebClient configuration
@Configuration
public class ApiConfig {    
  @Bean    
  WebClient abstractEmailClient(WebClient.Builder builder) {        
    return builder.baseUrl("https://emailvalidation.abstractapi.com/v1").build();    
  }
}

// 3. Service to call the API
@Service
public class EmailValidationService {    
  private final WebClient client;    
  @Value("${abstract.email.api-key}")    
  private String apiKey;    

  public EmailValidationService(WebClient abstractEmailClient) {        
    this.client = abstractEmailClient;    
  }    
  public Mono<AbstractEmailResponse> validate(String email) {        
    return client.get()            
      .uri(uriBuilder -> uriBuilder                
        .queryParam("api_key", apiKey)                
        .queryParam("email", email).build())            
      .retrieve()            
      .bodyToMono(AbstractEmailResponse.class);    
  }
}

// 4. Use in a custom validator
@Component
public class EmailValidator implements ConstraintValidator<ValidEmail, String> {    @Autowired   
  private EmailValidationService validationService;    
  
  @Override    
  public boolean isValid(String email, ConstraintValidatorContext context) {        
    if (email == null || email.isBlank()) {            
      return true; // Let @NotBlank handle this        
    }        
    AbstractEmailResponse response = validationService.validate(email)                                     
    	.block(Duration.ofSeconds(5));                
    
    return response != null                
        && "DELIVERABLE".equals(response.deliverability())                
        && response.quality_score() > 0.7;    
  }
}

When the service calls the API, it receives a JSON response with rich details about the email address. Here is a sample response for a valid email.

{
  "email":"johnsmith@gmail.com",
  "autocorrect":"",
  "deliverability":"DELIVERABLE",
  "quality_score":0.9,
  "is_valid_format":{"value":true,"text":"TRUE"},
  "is_free_email":{"value":true,"text":"TRUE"},
  "is_disposable_email":{"value":false,"text":"FALSE"},
  "is_role_email":{"value":false,"text":"FALSE"},
  "is_catchall_email":{"value":false,"text":"FALSE"},
  "is_mx_found":{"value":true,"text":"TRUE"},
  "is_smtp_valid":{"value":true,"text":"TRUE"}
}

This response tells you several key facts:

  • The format is correct, and the API suggests no autocorrection.
  • Abstract could reach the mail exchange (MX) server and confirm the SMTP status, so the mailbox almost certainly exists.
  • The domain is a free provider but not a disposable one. It is a personal address, not a role-based one like support@ or admin@.
  • A high quality_score with a DELIVERABLE status means you can safely accept the email for user signup.

Final Thoughts

Traditional validation through regular expressions often fails. It cannot detect disposable domains, catch-all addresses, or simple typos. Abstract API offers a robust alternative with its multi-layer checks.

To reliably validate user emails, consider an account on Abstract API and get your free API key.

Validate Emails with Abstract API
Improve your application's data quality by adding reliable email validation to your Spring Boot project.
Get started for free

Related Articles

Phone Validation
key now
Get your free
stars rating
4.8 from 1,863 votes
See why the best developers build on Abstract
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
No credit card required