EmailVerify LogoEmailVerify

Go SDK

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

The official EmailVerify SDK for Go provides idiomatic Go interfaces for email verification with built-in concurrency support.

Installation

go get github.com/emailverify/go-sdk

Quick Start

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

Configuration

Client Options

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

Available Options

// Set request timeout
emailverify.WithTimeout(30 * time.Second)

// Set number of retries
emailverify.WithRetries(3)

// Set custom base URL
emailverify.WithBaseURL("https://custom-api.example.com")

// Set custom HTTP client
emailverify.WithHTTPClient(&http.Client{
    Timeout: 30 * time.Second,
})

Types

Verification Result

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"`
}

Bulk Job

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"`
}

Single Verification

Basic Verification

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)

With Options

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

Context with Timeout

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("Verification timed out")
    }
    log.Fatal(err)
}

Bulk Verification

Submit Job

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)

Check Status

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)

Get Results

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

With Webhook

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

Concurrent Verification

Using Goroutines

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
}

With Worker Pool

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

    // Start workers
    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
            }
        }()
    }

    // Send emails
    go func() {
        for _, email := range emails {
            emailChan <- email
        }
        close(emailChan)
    }()

    // Close results when done
    go func() {
        wg.Wait()
        close(resultChan)
    }()

    return resultChan
}

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

Using 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 // capture loop variables
        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
}

Error Handling

Error Types

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("Invalid API key")
    case *errors.RateLimitError:
        log.Printf("Rate limited. Retry after %v", e.RetryAfter)
    case *errors.ValidationError:
        log.Printf("Invalid input: %s", e.Message)
    case *errors.APIError:
        log.Printf("API error: %s (code: %s)", e.Message, e.Code)
    default:
        log.Printf("Unknown error: %v", err)
    }
}

Custom Error Handler

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

        // Check if we should retry
        if rateLimitErr, ok := err.(*errors.RateLimitError); ok {
            time.Sleep(rateLimitErr.RetryAfter)
            continue
        }

        // Don't retry validation errors
        if _, ok := err.(*errors.ValidationError); ok {
            return nil, err
        }

        // Exponential backoff for other errors
        time.Sleep(time.Duration(attempt+1) * time.Second)
    }

    return nil, lastErr
}

Credit Management

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)

Framework Integration

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": "Verification failed"})
            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": "Invalid request"})
        }

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

        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": "Invalid request"})
        }

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

        return c.JSON(result)
    })

    return app
}

Complete Example

Email Validation Service

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: "Could not verify email address",
        }
    }

    // Reject invalid emails
    if result.Status == "invalid" {
        return ValidationResult{
            Valid:   false,
            Reason:  "invalid_email",
            Message: "This email address is invalid",
        }
    }

    // Reject disposable emails
    if result.Result.Disposable {
        return ValidationResult{
            Valid:   false,
            Reason:  "disposable",
            Message: "Please use a permanent email address",
        }
    }

    // Warn about role-based emails but allow
    if result.Result.Role {
        return ValidationResult{
            Valid:   true,
            Reason:  "role_based",
            Message: "Using a personal email is recommended",
            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("Invalid: %s - %s", result.Reason, result.Message)
        return
    }

    log.Printf("Valid email with score: %.2f", result.Score)
}

Best Practices

1. Always Use Context

// Set timeout for all operations
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

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

2. Handle Nil Pointers

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

3. Use Connection Pooling

// Reuse the client across requests
var client *emailverify.Client

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

Next Steps

On this page