Java SDK
Java email checker SDK. Maven/Gradle setup, verify emails with Java. Code examples included.
El SDK oficial de EmailVerify para Java proporciona una interfaz robusta para verificación de correo electrónico con soporte para integración con Spring Boot.
Instalación
Maven
<dependency>
<groupId>com.emailverify</groupId>
<artifactId>emailverify-java</artifactId>
<version>1.0.0</version>
</dependency>Gradle
implementation 'com.emailverify:emailverify-java:1.0.0'Requisitos
- Java 11 o superior
- Maven o Gradle
Inicio rápido
import com.emailverify.Client;
import com.emailverify.model.VerificationResult;
public class Main {
public static void main(String[] args) {
Client client = new Client(System.getenv("EMAILVERIFY_API_KEY"));
VerificationResult result = client.verify("user@example.com");
System.out.println("Estado: " + result.getStatus());
System.out.println("Puntuación: " + result.getScore());
}
}Configuración
Constructor del cliente
import com.emailverify.Client;
import java.time.Duration;
Client client = Client.builder()
.apiKey(System.getenv("EMAILVERIFY_API_KEY"))
.timeout(Duration.ofSeconds(30))
.retries(3)
.baseUrl("https://api.emailverify.ai")
.build();Propiedades de configuración
| Propiedad | Tipo | Predeterminado | Descripción |
|---|---|---|---|
apiKey | String | Requerido | Tu clave API |
timeout | Duration | 30s | Tiempo de espera de solicitud |
retries | int | 3 | Número de intentos de reintento |
baseUrl | String | URL de API | Endpoint de API personalizado |
Tipos
VerificationResult
public class VerificationResult {
private String email;
private String status; // "valid", "invalid", "unknown", "accept_all"
private ResultDetails result;
private double score;
private String reason;
// Getters...
}
public class ResultDetails {
private Boolean deliverable;
private boolean validFormat;
private boolean validDomain;
private boolean validMx;
private boolean disposable;
private boolean role;
private boolean catchall;
private boolean free;
private Boolean smtpValid;
// Getters...
}BulkJob
public class BulkJob {
private String id;
private String status; // "pending", "processing", "completed", "failed"
private int total;
private int processed;
private int valid;
private int invalid;
private int unknown;
private Instant createdAt;
private Instant completedAt;
// Getters...
}Verificación individual
Verificación básica
VerificationResult result = client.verify("user@example.com");
System.out.println("Correo electrónico: " + result.getEmail());
System.out.println("Estado: " + result.getStatus());
System.out.println("Puntuación: " + result.getScore());
System.out.println("Entregable: " + result.getResult().getDeliverable());
System.out.println("Desechable: " + result.getResult().isDisposable());Verificación con opciones
import com.emailverify.model.VerifyOptions;
VerifyOptions options = VerifyOptions.builder()
.smtpCheck(true)
.timeout(Duration.ofSeconds(5))
.build();
VerificationResult result = client.verify("user@example.com", options);Verificación asíncrona
import java.util.concurrent.CompletableFuture;
CompletableFuture<VerificationResult> future = client.verifyAsync("user@example.com");
future.thenAccept(result -> {
System.out.println("Estado: " + result.getStatus());
}).exceptionally(ex -> {
System.err.println("Error: " + ex.getMessage());
return null;
});Verificación masiva
Enviar trabajo
import java.util.Arrays;
import java.util.List;
List<String> emails = Arrays.asList(
"user1@example.com",
"user2@example.com",
"user3@example.com"
);
BulkJob job = client.verifyBulk(emails);
System.out.println("ID del trabajo: " + job.getId());Verificar estado
BulkJob status = client.getBulkJobStatus(job.getId());
System.out.println("Estado: " + status.getStatus());
System.out.println("Progreso: " + status.getProcessed() + "/" + status.getTotal());
System.out.println("Válidos: " + status.getValid());
System.out.println("Inválidos: " + status.getInvalid());Obtener resultados
List<VerificationResult> results = client.getBulkJobResults(job.getId());
for (VerificationResult result : results) {
System.out.println(result.getEmail() + ": " + result.getStatus());
}Con webhook
import com.emailverify.model.BulkOptions;
BulkOptions options = BulkOptions.builder()
.webhookUrl("https://tu-dominio.com/webhooks/emailverify")
.build();
BulkJob job = client.verifyBulk(emails, options);Gestión de créditos
import com.emailverify.model.Credits;
Credits credits = client.getCredits();
System.out.println("Disponibles: " + credits.getAvailable());
System.out.println("Usados: " + credits.getUsed());
System.out.println("Total: " + credits.getTotal());Manejo de errores
Tipos de excepciones
import com.emailverify.exception.*;
try {
VerificationResult result = client.verify("invalid-email");
} catch (AuthenticationException e) {
System.err.println("Clave API inválida");
} catch (RateLimitException e) {
System.err.println("Límite de tasa alcanzado. Reintentar después de " + e.getRetryAfter() + " segundos");
} catch (ValidationException e) {
System.err.println("Entrada inválida: " + e.getMessage());
} catch (EmailVerifyException e) {
System.err.println("Error de API: " + e.getMessage());
}Manejador de excepciones personalizado
public class VerificationService {
private final Client client;
public Optional<VerificationResult> safeVerify(String email) {
try {
return Optional.of(client.verify(email));
} catch (RateLimitException e) {
logger.warn("Límite de tasa alcanzado, reintentar después de: {}", e.getRetryAfter());
return Optional.empty();
} catch (EmailVerifyException e) {
logger.error("Verificación fallida: {}", e.getMessage());
return Optional.empty();
}
}
}Integración con Spring Boot
Dependencia
Añadir el iniciador de Spring Boot:
<dependency>
<groupId>com.emailverify</groupId>
<artifactId>emailverify-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>Configuración
# application.yml
emailverify:
api-key: ${EMAILVERIFY_API_KEY}
timeout: 30s
retries: 3O en application.properties:
emailverify.api-key=${EMAILVERIFY_API_KEY}
emailverify.timeout=30s
emailverify.retries=3Configuración automática
El cliente se configura automáticamente y está disponible para inyección:
import com.emailverify.Client;
import org.springframework.stereotype.Service;
@Service
public class EmailVerificationService {
private final Client emailVerifyClient;
public EmailVerificationService(Client emailVerifyClient) {
this.emailVerifyClient = emailVerifyClient;
}
public boolean isValidEmail(String email) {
VerificationResult result = emailVerifyClient.verify(email);
return "valid".equals(result.getStatus());
}
}Controlador REST
import com.emailverify.Client;
import com.emailverify.model.VerificationResult;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/verify")
public class VerificationController {
private final Client client;
public VerificationController(Client client) {
this.client = client;
}
@PostMapping
public ResponseEntity<?> verify(@RequestBody VerifyRequest request) {
try {
VerificationResult result = client.verify(request.getEmail());
return ResponseEntity.ok(new VerifyResponse(
result.getEmail(),
result.getStatus(),
result.getScore()
));
} catch (Exception e) {
return ResponseEntity.internalServerError()
.body(new ErrorResponse("Verificación fallida"));
}
}
}
record VerifyRequest(String email) {}
record VerifyResponse(String email, String status, double score) {}
record ErrorResponse(String error) {}Anotación de validador personalizado
// Anotación
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = ValidEmailValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEmail {
String message() default "Dirección de correo electrónico inválida";
boolean rejectDisposable() default true;
double minScore() default 0.5;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// Validador
import com.emailverify.Client;
import com.emailverify.model.VerificationResult;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class ValidEmailValidator implements ConstraintValidator<ValidEmail, String> {
private final Client client;
private boolean rejectDisposable;
private double minScore;
public ValidEmailValidator(Client client) {
this.client = client;
}
@Override
public void initialize(ValidEmail annotation) {
this.rejectDisposable = annotation.rejectDisposable();
this.minScore = annotation.minScore();
}
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
if (email == null || email.isBlank()) {
return false;
}
try {
VerificationResult result = client.verify(email);
if (!"valid".equals(result.getStatus())) {
return false;
}
if (rejectDisposable && result.getResult().isDisposable()) {
return false;
}
return result.getScore() >= minScore;
} catch (Exception e) {
return false;
}
}
}
// Uso
public class RegisterRequest {
@ValidEmail(rejectDisposable = true, minScore = 0.7)
private String email;
// getters, setters...
}Servicio asíncrono
import com.emailverify.Client;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncVerificationService {
private final Client client;
public AsyncVerificationService(Client client) {
this.client = client;
}
@Async
public CompletableFuture<VerificationResult> verifyAsync(String email) {
return client.verifyAsync(email);
}
@Async
public CompletableFuture<List<VerificationResult>> verifyBatchAsync(List<String> emails) {
return CompletableFuture.supplyAsync(() -> {
BulkJob job = client.verifyBulk(emails);
// Sondear para finalización
while (true) {
BulkJob status = client.getBulkJobStatus(job.getId());
if ("completed".equals(status.getStatus())) {
break;
}
if ("failed".equals(status.getStatus())) {
throw new RuntimeException("Trabajo masivo fallido");
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
return client.getBulkJobResults(job.getId());
});
}
}Ejemplos completos
Servicio de registro
import com.emailverify.Client;
import com.emailverify.model.VerificationResult;
public class RegistrationService {
private final Client client;
public RegistrationService(Client client) {
this.client = client;
}
public ValidationResult validateEmail(String email) {
VerificationResult result = client.verify(email);
// Rechazar correos electrónicos inválidos
if ("invalid".equals(result.getStatus())) {
return ValidationResult.invalid("invalid_email",
"Esta dirección de correo electrónico es inválida");
}
// Rechazar correos electrónicos desechables
if (result.getResult().isDisposable()) {
return ValidationResult.invalid("disposable",
"Por favor usa una dirección de correo electrónico permanente");
}
// Advertir sobre correos electrónicos basados en roles
if (result.getResult().isRole()) {
return ValidationResult.warning("role_based",
"Se recomienda usar un correo electrónico personal",
result.getScore());
}
return ValidationResult.valid(result.getScore());
}
}
class ValidationResult {
private final boolean valid;
private final String reason;
private final String message;
private final Double score;
private ValidationResult(boolean valid, String reason, String message, Double score) {
this.valid = valid;
this.reason = reason;
this.message = message;
this.score = score;
}
public static ValidationResult valid(double score) {
return new ValidationResult(true, null, null, score);
}
public static ValidationResult invalid(String reason, String message) {
return new ValidationResult(false, reason, message, null);
}
public static ValidationResult warning(String reason, String message, double score) {
return new ValidationResult(true, reason, message, score);
}
// Getters...
}Verificación concurrente
import com.emailverify.Client;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class ConcurrentVerifier {
private final Client client;
private final ExecutorService executor;
public ConcurrentVerifier(Client client, int threads) {
this.client = client;
this.executor = Executors.newFixedThreadPool(threads);
}
public List<VerificationResult> verifyAll(List<String> emails) {
List<CompletableFuture<VerificationResult>> futures = emails.stream()
.map(email -> CompletableFuture.supplyAsync(
() -> client.verify(email), executor))
.collect(Collectors.toList());
return futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
public void shutdown() {
executor.shutdown();
}
}
// Uso
ConcurrentVerifier verifier = new ConcurrentVerifier(client, 10);
try {
List<String> emails = Arrays.asList("user1@example.com", "user2@example.com");
List<VerificationResult> results = verifier.verifyAll(emails);
results.forEach(r -> System.out.println(r.getEmail() + ": " + r.getStatus()));
} finally {
verifier.shutdown();
}Mejores prácticas
1. Usar pooling de conexiones
// El cliente usa pooling de conexiones por defecto
// Para aplicaciones de alto rendimiento, configurar el tamaño del pool
Client client = Client.builder()
.apiKey(apiKey)
.maxConnections(100)
.build();2. Manejar campos anulables
VerificationResult result = client.verify(email);
// Usar Optional para campos anulables
Optional.ofNullable(result.getResult().getDeliverable())
.ifPresent(deliverable -> System.out.println("Entregable: " + deliverable));3. Gestión de recursos
// El cliente implementa AutoCloseable
try (Client client = new Client(apiKey)) {
VerificationResult result = client.verify(email);
// Procesar resultado
}