Go Email Validation

Complete guide to email validation in Go

What You'll Learn

  • Integrate VerifyForge API using Go's HTTP client
  • Create reusable validation functions
  • Handle errors with Go patterns
  • Implement concurrent bulk validation
  • Best practices for production

Prerequisites

  • Go 1.20+ installed
  • Basic knowledge of Go
  • VerifyForge API key (get free key)

Quick Start

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
)

func main() {
	apiKey := "your_api_key"
	email := "user@example.com"

	client := &http.Client{}
	req, _ := http.NewRequest("GET",
		"https://verifyforge.com/api/validate?email="+url.QueryEscape(email),
		nil)

	req.Header.Set("X-API-Key", apiKey)

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)

	var result map[string]interface{}
	json.Unmarshal(body, &result)

	data := result["data"].(map[string]interface{})
	fmt.Printf("Valid: %v\n", data["isValid"])
}

Email Validator Package

// emailvalidator/validator.go
package emailvalidator

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"time"
)

type Client struct {
	APIKey  string
	BaseURL string
	client  *http.Client
}

type ValidationResult struct {
	Email       string `json:"email"`
	IsValid     bool   `json:"isValid"`
	Reachability string `json:"reachability"`
	Disposable  bool   `json:"disposable"`
	RoleAccount bool   `json:"roleAccount"`
	FreeProvider bool  `json:"freeProvider"`
	Suggestion  string `json:"suggestion,omitempty"`
}

type ValidationResponse struct {
	Success bool             `json:"success"`
	Data    ValidationResult `json:"data"`
}

func NewClient(apiKey string) *Client {
	return &Client{
		APIKey:  apiKey,
		BaseURL: "https://verifyforge.com",
		client: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

func (c *Client) Validate(email string) (*ValidationResult, error) {
	req, err := http.NewRequest("GET",
		fmt.Sprintf("%s/api/validate?email=%s", c.BaseURL, url.QueryEscape(email)),
		nil)

	if err != nil {
		return nil, err
	}

	req.Header.Set("X-API-Key", c.APIKey)

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("API error: %d", resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var result ValidationResponse
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, err
	}

	return &result.Data, nil
}

func (c *Client) ValidateBulk(emails []string) ([]ValidationResult, error) {
	payload, err := json.Marshal(map[string][]string{"emails": emails})
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST",
		fmt.Sprintf("%s/api/validate/bulk", c.BaseURL),
		bytes.NewBuffer(payload))

	if err != nil {
		return nil, err
	}

	req.Header.Set("X-API-Key", c.APIKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var result struct {
		Data struct {
			Results []ValidationResult `json:"results"`
		} `json:"data"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return nil, err
	}

	return result.Data.Results, nil
}

HTTP Handler Example

package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"

	"yourapp/emailvalidator"
)

var validator *emailvalidator.Client

func init() {
	validator = emailvalidator.NewClient(os.Getenv("VERIFYFORGE_API_KEY"))
}

func validateHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		Email string `json:"email"`
	}

	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request", http.StatusBadRequest)
		return
	}

	result, err := validator.Validate(req.Email)
	if err != nil {
		http.Error(w, "Validation failed", http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"success": true,
		"data":    result,
	})
}

func main() {
	http.HandleFunc("/api/validate", validateHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

Concurrent Bulk Validation

package main

import (
	"sync"
	"yourapp/emailvalidator"
)

func validateConcurrent(emails []string, validator *emailvalidator.Client) map[string]*emailvalidator.ValidationResult {
	results := make(map[string]*emailvalidator.ValidationResult)
	var mu sync.Mutex
	var wg sync.WaitGroup

	for _, email := range emails {
		wg.Add(1)
		go func(e string) {
			defer wg.Done()

			result, err := validator.Validate(e)
			if err == nil {
				mu.Lock()
				results[e] = result
				mu.Unlock()
			}
		}(email)
	}

	wg.Wait()
	return results
}

Next Steps