EmailVerify LogoEmailVerify

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

PropiedadTipoPredeterminadoDescripción
apiKeyStringRequeridoTu clave API
timeoutDuration30sTiempo de espera de solicitud
retriesint3Número de intentos de reintento
baseUrlStringURL de APIEndpoint 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: 3

O en application.properties:

emailverify.api-key=${EMAILVERIFY_API_KEY}
emailverify.timeout=30s
emailverify.retries=3

Configuració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
}

Próximos pasos

On this page