Spring email verification
Verify emails in Spring Boot with Verifly
Add a live email verification step to any Spring Boot app with RestTemplate or WebClient inside a @Service. Verifly is an API-first, pay-as-you-go service — call it from a bean, map the JSON verdict to a record, and even enforce it as a bean-validation constraint.
@Service
public class EmailVerifier {
private final RestTemplate rest = new RestTemplate();
public record Verdict(String result, boolean is_valid,
boolean disposable, boolean role) {}
public Verdict verify(String email) {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth("vf_YOUR_KEY"); // inject from application.yml
String url = UriComponentsBuilder
.fromHttpUrl("https://verifly.email/api/v1/verify")
.queryParam("email", email)
.toUriString();
return rest.exchange(url, HttpMethod.GET,
new HttpEntity<>(headers), Verdict.class).getBody();
}
}Real-time SMTP mailbox checks
Single, batch, and async bulk verification
Disposable, role account, and catch-all detection
Pay-as-you-go credits with no subscription lock-in
Search fit
Built for Spring email verification
Use Verifly when you need a simple API, predictable pricing, and clean JSON results before emails hit your product, CRM, or campaign tool.
Email verification in a Spring @Service
Spring's Hibernate-backed @Email annotation checks that an address is syntactically valid, and no more. user@dead-domain.com sails through @Email and still bounces the moment your JavaMailSender tries to deliver. The real question — does this mailbox accept mail — is answered by an SMTP handshake, which Verifly performs for you over one HTTPS call. Wrap that call in a @Service bean so the rest of your application depends on a clean interface rather than raw HTTP.
Inside the service you can use either client Spring ships. RestTemplate is the familiar synchronous choice: set a Bearer header, build the URL with UriComponentsBuilder, and let Jackson deserialize the JSON straight into a Java record. If your stack is reactive, use WebClient instead and return a Mono. Either way the response carries a result field of deliverable, undeliverable, or risky plus boolean flags for disposable, role, catch_all, and smtp, which map onto record components automatically.
Keep the key out of source: bind it from application.yml or an environment variable through @Value, never a string literal in production. Pricing is pay-as-you-go from $2 per 1,000 checks down to $0.60 per 1,000 at volume, and you can self-register for 100 free credits with no card at the autonomous register endpoint.
Enforce it as a bean-validation constraint
Because Spring already validates DTOs with Jakarta Bean Validation, you can make deliverability a first-class constraint. Define a @ValidEmail annotation backed by a ConstraintValidator that calls your EmailVerifier service, and Spring will run it automatically on any @Valid request body. Fail open inside the validator — return true on a network error — so a Verifly outage never turns your signup endpoint into a 400 machine.
@Constraint(validatedBy = DeliverableValidator.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEmail {
String message() default "Email is not deliverable";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@Component
class DeliverableValidator implements ConstraintValidator<ValidEmail, String> {
private final EmailVerifier verifier;
DeliverableValidator(EmailVerifier verifier) { this.verifier = verifier; }
@Override
public boolean isValid(String email, ConstraintValidatorContext ctx) {
if (email == null) return true; // let @NotNull handle emptiness
try {
var v = verifier.verify(email);
return !"undeliverable".equals(v.result()) && !v.disposable();
} catch (RestClientException e) {
return true; // fail open on a network error
}
}
}Batch-verify a list with WebClient
For cleaning a list rather than a single field, do not loop the single endpoint — POST them together to /api/v1/verify/batch. It accepts a JSON body with an emails array and returns a results array in the same order. WebClient handles this cleanly: post the body, deserialize into a record, and stream the results down to the deliverable addresses.
public record Item(String email, String result, boolean disposable) {}
public record BatchResponse(List<Item> results) {}
WebClient client = WebClient.builder()
.baseUrl("https://verifly.email/api/v1")
.defaultHeaders(h -> h.setBearerAuth("vf_YOUR_KEY"))
.build();
List<String> emails = List.of("ada@example.com", "info@acme.com", "x@disposable.tld");
BatchResponse batch = client.post()
.uri("/verify/batch")
.bodyValue(Map.of("emails", emails))
.retrieve()
.bodyToMono(BatchResponse.class)
.block();
List<String> kept = batch.results().stream()
.filter(i -> "deliverable".equals(i.result()) && !i.disposable())
.map(Item::email)
.toList();FAQ
Frequently asked questions
RestTemplate or WebClient for Verifly?
Both work. Use RestTemplate for a straightforward synchronous @Service — set a Bearer header and let Jackson map the JSON to a record. Use WebClient if your app is reactive or you want non-blocking batch calls returning a Mono. Verifly is a plain REST API, so either client fits.
How do I keep my Verifly key out of the code?
Bind it from application.yml or an environment variable with @Value("${verifly.key}") and pass it to headers.setBearerAuth(...). Never commit a literal key; the value is a Bearer secret that belongs in externalized config or a secrets manager.
Can I enforce deliverability with bean validation?
Yes. Define a @ValidEmail annotation backed by a ConstraintValidator that calls your EmailVerifier @Service. Spring runs it automatically on any @Valid DTO field, so a bad address is rejected before your controller logic ever runs.
How do I stop a Verifly outage from breaking signups?
Fail open inside the validator or service: catch RestClientException (or WebClientException) and return true / treat the address as acceptable. You only reject when Verifly positively reports undeliverable or disposable.
How do I verify a whole list of addresses?
POST them to /api/v1/verify/batch as a JSON emails array and deserialize the results array into a record list, then filter the stream on the result field. Batching is faster and cheaper than looping the single endpoint.
What does Spring email verification cost?
Pricing is pay-as-you-go from $2 per 1,000 checks down to $0.60 per 1,000 at volume, with 100 free credits when you self-register. There is no subscription. For AI agents, Verifly also exposes an MCP server at verifly.email/mcp.