EmailVerify LogoEmailVerify

Go SDK

Go email checker SDK. Install, configure, verify emails with Golang. Code examples included.

EmailVerify 官方 Go SDK 为邮箱验证提供符合 Go 语言习惯的接口,内置并发支持。

安装

go get github.com/emailverify/go-sdk

快速开始

package main

import (
    "context"
    "fmt"
    "os"

    emailverify "github.com/emailverify/go-sdk"
)

func main() {
    client := emailverify.NewClient(os.Getenv("EMAILVERIFY_API_KEY"))

    ctx := context.Background()
    result, err := client.Verify(ctx, "user@example.com")
    if err != nil {
        panic(err)
    }

    fmt.Printf("Status: %s\n", result.Status)
    fmt.Printf("Score: %.2f\n", result.Score)
}

配置

客户端选项

client := emailverify.NewClient(
    os.Getenv("EMAILVERIFY_API_KEY"),
    emailverify.WithTimeout(30*time.Second),
    emailverify.WithRetries(3),
    emailverify.WithBaseURL("https://api.emailverify.ai"),
)

可用选项

// 设置请求超时
emailverify.WithTimeout(30 * time.Second)

// 设置重试次数
emailverify.WithRetries(3)

// 设置自定义 API URL
emailverify.WithBaseURL("https://custom-api.example.com")

// 设置自定义 HTTP 客户端
emailverify.WithHTTPClient(&http.Client{
    Timeout: 30 * time.Second,
})

类型

验证结果

type VerificationResult struct {
    Email  string        `json:"email"`
    Status string        `json:"status"` // "valid"、"invalid"、"unknown"、"accept_all"
    Result ResultDetails `json:"result"`
    Score  float64       `json:"score"`
    Reason *string       `json:"reason"`
}

type ResultDetails struct {
    Deliverable *bool `json:"deliverable"`
    ValidFormat bool  `json:"valid_format"`
    ValidDomain bool  `json:"valid_domain"`
    ValidMX     bool  `json:"valid_mx"`
    Disposable  bool  `json:"disposable"`
    Role        bool  `json:"role"`
    Catchall    bool  `json:"catchall"`
    Free        bool  `json:"free"`
    SMTPValid   *bool `json:"smtp_valid"`
}

批量任务

type BulkJob struct {
    ID          string    `json:"id"`
    Status      string    `json:"status"` // "pending"、"processing"、"completed"、"failed"
    Total       int       `json:"total"`
    Processed   int       `json:"processed"`
    Valid       int       `json:"valid"`
    Invalid     int       `json:"invalid"`
    Unknown     int       `json:"unknown"`
    CreatedAt   time.Time `json:"created_at"`
    CompletedAt *time.Time `json:"completed_at"`
}

单个验证

基本验证

ctx := context.Background()
result, err := client.Verify(ctx, "user@example.com")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Email: %s\n", result.Email)
fmt.Printf("Status: %s\n", result.Status)
fmt.Printf("Score: %.2f\n", result.Score)
fmt.Printf("Disposable: %v\n", result.Result.Disposable)

使用选项

result, err := client.Verify(ctx, "user@example.com",
    emailverify.WithSMTPCheck(true),
    emailverify.WithVerifyTimeout(5*time.Second),
)

带超时的 Context

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

result, err := client.Verify(ctx, "user@example.com")
if err != nil {
    if ctx.Err() == context.DeadlineExceeded {
        log.Println("验证超时")
    }
    log.Fatal(err)
}

批量验证

提交任务

emails := []string{
    "user1@example.com",
    "user2@example.com",
    "user3@example.com",
}

job, err := client.VerifyBulk(ctx, emails)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Job ID: %s\n", job.ID)

检查状态

status, err := client.GetBulkJobStatus(ctx, job.ID)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Status: %s\n", status.Status)
fmt.Printf("Progress: %d/%d\n", status.Processed, status.Total)

获取结果

results, err := client.GetBulkJobResults(ctx, job.ID)
if err != nil {
    log.Fatal(err)
}

for _, result := range results {
    fmt.Printf("%s: %s\n", result.Email, result.Status)
}

使用 Webhook

job, err := client.VerifyBulk(ctx, emails,
    emailverify.WithWebhookURL("https://your-domain.com/webhooks/emailverify"),
)

并发验证

使用 Goroutine

func verifyEmails(ctx context.Context, client *emailverify.Client, emails []string) []VerificationResult {
    results := make([]VerificationResult, len(emails))
    var wg sync.WaitGroup

    for i, email := range emails {
        wg.Add(1)
        go func(idx int, email string) {
            defer wg.Done()
            result, err := client.Verify(ctx, email)
            if err != nil {
                log.Printf("验证 %s 时出错: %v", email, err)
                return
            }
            results[idx] = *result
        }(i, email)
    }

    wg.Wait()
    return results
}

使用工作池

func verifyWithWorkerPool(ctx context.Context, client *emailverify.Client, emails []string, workers int) <-chan *emailverify.VerificationResult {
    emailChan := make(chan string, len(emails))
    resultChan := make(chan *emailverify.VerificationResult, len(emails))

    // 启动工作线程
    var wg sync.WaitGroup
    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for email := range emailChan {
                result, err := client.Verify(ctx, email)
                if err != nil {
                    log.Printf("错误: %v", err)
                    continue
                }
                resultChan <- result
            }
        }()
    }

    // 发送邮箱
    go func() {
        for _, email := range emails {
            emailChan <- email
        }
        close(emailChan)
    }()

    // 完成后关闭结果通道
    go func() {
        wg.Wait()
        close(resultChan)
    }()

    return resultChan
}

// 使用方法
results := verifyWithWorkerPool(ctx, client, emails, 10)
for result := range results {
    fmt.Printf("%s: %s\n", result.Email, result.Status)
}

使用 errgroup

import "golang.org/x/sync/errgroup"

func verifyEmailsConcurrently(ctx context.Context, client *emailverify.Client, emails []string) ([]*emailverify.VerificationResult, error) {
    g, ctx := errgroup.WithContext(ctx)
    results := make([]*emailverify.VerificationResult, len(emails))

    for i, email := range emails {
        i, email := i, email // 捕获循环变量
        g.Go(func() error {
            result, err := client.Verify(ctx, email)
            if err != nil {
                return fmt.Errorf("验证 %s: %w", email, err)
            }
            results[i] = result
            return nil
        })
    }

    if err := g.Wait(); err != nil {
        return nil, err
    }

    return results, nil
}

错误处理

错误类型

import "github.com/emailverify/go-sdk/errors"

result, err := client.Verify(ctx, email)
if err != nil {
    switch e := err.(type) {
    case *errors.AuthenticationError:
        log.Fatal("API 密钥无效")
    case *errors.RateLimitError:
        log.Printf("访问频率受限。请在 %v 后重试", e.RetryAfter)
    case *errors.ValidationError:
        log.Printf("输入无效: %s", e.Message)
    case *errors.APIError:
        log.Printf("API 错误: %s (代码: %s)", e.Message, e.Code)
    default:
        log.Printf("未知错误: %v", err)
    }
}

自定义错误处理器

func verifyWithRetry(ctx context.Context, client *emailverify.Client, email string) (*emailverify.VerificationResult, error) {
    var lastErr error

    for attempt := 0; attempt < 3; attempt++ {
        result, err := client.Verify(ctx, email)
        if err == nil {
            return result, nil
        }

        lastErr = err

        // 检查是否应该重试
        if rateLimitErr, ok := err.(*errors.RateLimitError); ok {
            time.Sleep(rateLimitErr.RetryAfter)
            continue
        }

        // 不要重试验证错误
        if _, ok := err.(*errors.ValidationError); ok {
            return nil, err
        }

        // 对其他错误使用指数退避
        time.Sleep(time.Duration(attempt+1) * time.Second)
    }

    return nil, lastErr
}

额度管理

credits, err := client.GetCredits(ctx)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("可用: %d\n", credits.Available)
fmt.Printf("已使用: %d\n", credits.Used)
fmt.Printf("总计: %d\n", credits.Total)

框架集成

Gin

import "github.com/gin-gonic/gin"

func setupRouter(client *emailverify.Client) *gin.Engine {
    r := gin.Default()

    r.POST("/verify", func(c *gin.Context) {
        var req struct {
            Email string `json:"email" binding:"required,email"`
        }

        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(400, gin.H{"error": err.Error()})
            return
        }

        result, err := client.Verify(c.Request.Context(), req.Email)
        if err != nil {
            c.JSON(500, gin.H{"error": "验证失败"})
            return
        }

        c.JSON(200, result)
    })

    return r
}

Echo

import "github.com/labstack/echo/v4"

func setupRoutes(e *echo.Echo, client *emailverify.Client) {
    e.POST("/verify", func(c echo.Context) error {
        var req struct {
            Email string `json:"email"`
        }

        if err := c.Bind(&req); err != nil {
            return c.JSON(400, map[string]string{"error": "请求无效"})
        }

        result, err := client.Verify(c.Request().Context(), req.Email)
        if err != nil {
            return c.JSON(500, map[string]string{"error": "验证失败"})
        }

        return c.JSON(200, result)
    })
}

Fiber

import "github.com/gofiber/fiber/v2"

func setupFiber(client *emailverify.Client) *fiber.App {
    app := fiber.New()

    app.Post("/verify", func(c *fiber.Ctx) error {
        var req struct {
            Email string `json:"email"`
        }

        if err := c.BodyParser(&req); err != nil {
            return c.Status(400).JSON(fiber.Map{"error": "请求无效"})
        }

        result, err := client.Verify(context.Background(), req.Email)
        if err != nil {
            return c.Status(500).JSON(fiber.Map{"error": "验证失败"})
        }

        return c.JSON(result)
    })

    return app
}

完整示例

邮箱验证服务

package main

import (
    "context"
    "log"
    "os"

    emailverify "github.com/emailverify/go-sdk"
)

type ValidationResult struct {
    Valid   bool   `json:"valid"`
    Reason  string `json:"reason,omitempty"`
    Message string `json:"message,omitempty"`
    Score   float64 `json:"score,omitempty"`
}

type EmailValidator struct {
    client *emailverify.Client
}

func NewEmailValidator() *EmailValidator {
    return &EmailValidator{
        client: emailverify.NewClient(os.Getenv("EMAILVERIFY_API_KEY")),
    }
}

func (v *EmailValidator) ValidateForRegistration(ctx context.Context, email string) ValidationResult {
    result, err := v.client.Verify(ctx, email)
    if err != nil {
        return ValidationResult{
            Valid:   false,
            Reason:  "verification_error",
            Message: "无法验证邮箱地址",
        }
    }

    // 拒绝无效邮箱
    if result.Status == "invalid" {
        return ValidationResult{
            Valid:   false,
            Reason:  "invalid_email",
            Message: "此邮箱地址无效",
        }
    }

    // 拒绝一次性邮箱
    if result.Result.Disposable {
        return ValidationResult{
            Valid:   false,
            Reason:  "disposable",
            Message: "请使用永久邮箱地址",
        }
    }

    // 警告角色邮箱但允许
    if result.Result.Role {
        return ValidationResult{
            Valid:   true,
            Reason:  "role_based",
            Message: "建议使用个人邮箱",
            Score:   result.Score,
        }
    }

    return ValidationResult{
        Valid: true,
        Score: result.Score,
    }
}

func main() {
    validator := NewEmailValidator()

    ctx := context.Background()
    result := validator.ValidateForRegistration(ctx, "user@example.com")

    if !result.Valid {
        log.Printf("无效: %s - %s", result.Reason, result.Message)
        return
    }

    log.Printf("有效邮箱,分数: %.2f", result.Score)
}

最佳实践

1. 始终使用 Context

// 为所有操作设置超时
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

result, err := client.Verify(ctx, email)

2. 处理 Nil 指针

if result.Result.Deliverable != nil {
    fmt.Printf("可递送: %v\n", *result.Result.Deliverable)
}

3. 使用连接池

// 在请求中重用客户端
var client *emailverify.Client

func init() {
    client = emailverify.NewClient(os.Getenv("EMAILVERIFY_API_KEY"))
}

下一步

On this page