EmailVerify LogoEmailVerify

Go

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)

// カスタムベース 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),
)

タイムアウト付きコンテキスト

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("Error verifying %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("Error: %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("verify %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 (code: %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("Available: %d\n", credits.Available)
fmt.Printf("Used: %d\n", credits.Used)
fmt.Printf("Total: %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("Deliverable: %v\n", *result.Result.Deliverable)
}

3. コネクションプーリングを使用

// リクエスト間でクライアントを再利用
var client *emailverify.Client

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

次のステップ

On this page