EmailVerify LogoEmailVerify

Java SDK

Java email checker SDK. Maven/Gradle setup, verify emails with Java. Code examples included.

官方 EmailVerify Java SDK 提供穩健的郵箱驗證介面,並支援 Spring Boot 整合。

安裝

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'

需求

  • Java 11 或更高版本
  • Maven 或 Gradle

快速入門

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("狀態: " + result.getStatus());
        System.out.println("分數: " + result.getScore());
    }
}

配置

Client Builder

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();

配置屬性

屬性類型預設值說明
apiKeyString必填您的 API Key
timeoutDuration30s請求逾時
retriesint3重試次數
baseUrlStringAPI URL自訂 API 端點

型別

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...
}

單一驗證

基本驗證

VerificationResult result = client.verify("user@example.com");

System.out.println("郵箱: " + result.getEmail());
System.out.println("狀態: " + result.getStatus());
System.out.println("分數: " + result.getScore());
System.out.println("可送達: " + result.getResult().getDeliverable());
System.out.println("一次性: " + result.getResult().isDisposable());

帶選項的驗證

import com.emailverify.model.VerifyOptions;

VerifyOptions options = VerifyOptions.builder()
    .smtpCheck(true)
    .timeout(Duration.ofSeconds(5))
    .build();

VerificationResult result = client.verify("user@example.com", options);

異步驗證

import java.util.concurrent.CompletableFuture;

CompletableFuture<VerificationResult> future = client.verifyAsync("user@example.com");

future.thenAccept(result -> {
    System.out.println("狀態: " + result.getStatus());
}).exceptionally(ex -> {
    System.err.println("錯誤: " + ex.getMessage());
    return null;
});

批量驗證

提交任務

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: " + job.getId());

檢查狀態

BulkJob status = client.getBulkJobStatus(job.getId());

System.out.println("狀態: " + status.getStatus());
System.out.println("進度: " + status.getProcessed() + "/" + status.getTotal());
System.out.println("有效: " + status.getValid());
System.out.println("無效: " + status.getInvalid());

獲取結果

List<VerificationResult> results = client.getBulkJobResults(job.getId());

for (VerificationResult result : results) {
    System.out.println(result.getEmail() + ": " + result.getStatus());
}

使用 Webhook

import com.emailverify.model.BulkOptions;

BulkOptions options = BulkOptions.builder()
    .webhookUrl("https://your-domain.com/webhooks/emailverify")
    .build();

BulkJob job = client.verifyBulk(emails, options);

額度管理

import com.emailverify.model.Credits;

Credits credits = client.getCredits();

System.out.println("可用: " + credits.getAvailable());
System.out.println("已使用: " + credits.getUsed());
System.out.println("總計: " + credits.getTotal());

錯誤處理

異常類型

import com.emailverify.exception.*;

try {
    VerificationResult result = client.verify("invalid-email");
} catch (AuthenticationException e) {
    System.err.println("無效的 API Key");
} catch (RateLimitException e) {
    System.err.println("速率限制。請在 " + e.getRetryAfter() + " 秒後重試");
} catch (ValidationException e) {
    System.err.println("無效的輸入: " + e.getMessage());
} catch (EmailVerifyException e) {
    System.err.println("API 錯誤: " + e.getMessage());
}

自訂異常處理器

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("速率限制,請在 {} 秒後重試", e.getRetryAfter());
            return Optional.empty();
        } catch (EmailVerifyException e) {
            logger.error("驗證失敗: {}", e.getMessage());
            return Optional.empty();
        }
    }
}

Spring Boot 整合

依賴

新增 Spring Boot starter:

<dependency>
    <groupId>com.emailverify</groupId>
    <artifactId>emailverify-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

配置

# application.yml
emailverify:
  api-key: ${EMAILVERIFY_API_KEY}
  timeout: 30s
  retries: 3

或在 application.properties 中:

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

自動配置

客戶端會自動配置並可供注入:

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());
    }
}

REST Controller

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("驗證失敗"));
        }
    }
}

record VerifyRequest(String email) {}
record VerifyResponse(String email, String status, double score) {}
record ErrorResponse(String error) {}

自訂驗證器註解

// 註解
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 "無效的郵箱地址";
    boolean rejectDisposable() default true;
    double minScore() default 0.5;
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

// 驗證器
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;
        }
    }
}

// 使用方法
public class RegisterRequest {
    @ValidEmail(rejectDisposable = true, minScore = 0.7)
    private String email;

    // getters, setters...
}

異步服務

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);

            // 輪詢完成
            while (true) {
                BulkJob status = client.getBulkJobStatus(job.getId());
                if ("completed".equals(status.getStatus())) {
                    break;
                }
                if ("failed".equals(status.getStatus())) {
                    throw new RuntimeException("批量任務失敗");
                }
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                }
            }

            return client.getBulkJobResults(job.getId());
        });
    }
}

完整範例

註冊服務

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);

        // 拒絕無效郵箱
        if ("invalid".equals(result.getStatus())) {
            return ValidationResult.invalid("invalid_email",
                "此郵箱地址無效");
        }

        // 拒絕一次性郵箱
        if (result.getResult().isDisposable()) {
            return ValidationResult.invalid("disposable",
                "請使用永久郵箱地址");
        }

        // 警告角色郵箱
        if (result.getResult().isRole()) {
            return ValidationResult.warning("role_based",
                "建議使用個人郵箱",
                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...
}

並發驗證

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();
    }
}

// 使用方法
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();
}

最佳實踐

1. 使用連線池

// 客戶端預設使用連線池
// 對於高吞吐量應用程式,配置池大小
Client client = Client.builder()
    .apiKey(apiKey)
    .maxConnections(100)
    .build();

2. 處理可為 null 的欄位

VerificationResult result = client.verify(email);

// 對可為 null 的欄位使用 Optional
Optional.ofNullable(result.getResult().getDeliverable())
    .ifPresent(deliverable -> System.out.println("可送達: " + deliverable));

3. 資源管理

// 客戶端實作 AutoCloseable
try (Client client = new Client(apiKey)) {
    VerificationResult result = client.verify(email);
    // 處理結果
}

下一步

On this page