EmailVerify LogoEmailVerify

Go SDK

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

El SDK oficial de EmailVerify para Go proporciona interfaces idiomáticas de Go para verificación de correo electrónico con soporte de concurrencia integrado.

Instalación

go get github.com/emailverify/go-sdk

Inicio rápido

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("Estado: %s\n", result.Status)
    fmt.Printf("Puntuación: %.2f\n", result.Score)
}

Configuración

Opciones del cliente

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

Opciones disponibles

// Establecer tiempo de espera de solicitud
emailverify.WithTimeout(30 * time.Second)

// Establecer número de reintentos
emailverify.WithRetries(3)

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

// Establecer cliente HTTP personalizado
emailverify.WithHTTPClient(&http.Client{
    Timeout: 30 * time.Second,
})

Tipos

Resultado de verificación

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

Trabajo masivo

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

Verificación individual

Verificación básica

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

fmt.Printf("Correo electrónico: %s\n", result.Email)
fmt.Printf("Estado: %s\n", result.Status)
fmt.Printf("Puntuación: %.2f\n", result.Score)
fmt.Printf("Desechable: %v\n", result.Result.Disposable)

Con opciones

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

Contexto con tiempo de espera

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("Se agotó el tiempo de verificación")
    }
    log.Fatal(err)
}

Verificación masiva

Enviar trabajo

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("ID del trabajo: %s\n", job.ID)

Verificar estado

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

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

Obtener resultados

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

Con webhook

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

Verificación concurrente

Usando 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 al verificar %s: %v", email, err)
                return
            }
            results[idx] = *result
        }(i, email)
    }

    wg.Wait()
    return results
}

Con pool de trabajadores

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

    // Iniciar trabajadores
    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
            }
        }()
    }

    // Enviar correos electrónicos
    go func() {
        for _, email := range emails {
            emailChan <- email
        }
        close(emailChan)
    }()

    // Cerrar resultados cuando termine
    go func() {
        wg.Wait()
        close(resultChan)
    }()

    return resultChan
}

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

Usando 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 // capturar variables de bucle
        g.Go(func() error {
            result, err := client.Verify(ctx, email)
            if err != nil {
                return fmt.Errorf("verificar %s: %w", email, err)
            }
            results[i] = result
            return nil
        })
    }

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

    return results, nil
}

Manejo de errores

Tipos de errores

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("Clave API inválida")
    case *errors.RateLimitError:
        log.Printf("Límite de tasa alcanzado. Reintentar después de %v", e.RetryAfter)
    case *errors.ValidationError:
        log.Printf("Entrada inválida: %s", e.Message)
    case *errors.APIError:
        log.Printf("Error de API: %s (código: %s)", e.Message, e.Code)
    default:
        log.Printf("Error desconocido: %v", err)
    }
}

Manejador de errores personalizado

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

        // Verificar si debemos reintentar
        if rateLimitErr, ok := err.(*errors.RateLimitError); ok {
            time.Sleep(rateLimitErr.RetryAfter)
            continue
        }

        // No reintentar errores de validación
        if _, ok := err.(*errors.ValidationError); ok {
            return nil, err
        }

        // Retroceso exponencial para otros errores
        time.Sleep(time.Duration(attempt+1) * time.Second)
    }

    return nil, lastErr
}

Gestión de créditos

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

fmt.Printf("Disponibles: %d\n", credits.Available)
fmt.Printf("Usados: %d\n", credits.Used)
fmt.Printf("Total: %d\n", credits.Total)

Integración con frameworks

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": "Verificación fallida"})
            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": "Solicitud inválida"})
        }

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

        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": "Solicitud inválida"})
        }

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

        return c.JSON(result)
    })

    return app
}

Ejemplo completo

Servicio de validación de correo electrónico

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: "No se pudo verificar la dirección de correo electrónico",
        }
    }

    // Rechazar correos electrónicos inválidos
    if result.Status == "invalid" {
        return ValidationResult{
            Valid:   false,
            Reason:  "invalid_email",
            Message: "Esta dirección de correo electrónico es inválida",
        }
    }

    // Rechazar correos electrónicos desechables
    if result.Result.Disposable {
        return ValidationResult{
            Valid:   false,
            Reason:  "disposable",
            Message: "Por favor usa una dirección de correo electrónico permanente",
        }
    }

    // Advertir sobre correos electrónicos basados en roles pero permitir
    if result.Result.Role {
        return ValidationResult{
            Valid:   true,
            Reason:  "role_based",
            Message: "Se recomienda usar un correo electrónico personal",
            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("Inválido: %s - %s", result.Reason, result.Message)
        return
    }

    log.Printf("Correo electrónico válido con puntuación: %.2f", result.Score)
}

Mejores prácticas

1. Usar siempre contexto

// Establecer tiempo de espera para todas las operaciones
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

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

2. Manejar punteros nulos

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

3. Usar pooling de conexiones

// Reutilizar el cliente en todas las solicitudes
var client *emailverify.Client

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

Próximos pasos

On this page