CheckDisposable Emailcheckdisposable.email
← All guidesGo (Gin) guide · Go

Block disposable email signups in Go (Gin)

Add a small package-level function and call it in your signup handler. Works the same way in Echo, Chi, Fiber, or net/http — only the framework wiring changes.

The code

// internal/cde/cde.go
package cde

import (
	"context"
	"encoding/json"
	"net/http"
	"net/url"
	"os"
	"time"
)

var client = &http.Client{Timeout: 3 * time.Second}

func IsDisposable(ctx context.Context, email string) bool {
	u := "https://api.checkdisposable.email/v1/check?email=" + url.QueryEscape(email)
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
	if err != nil {
		return false
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("CDE_KEY"))
	res, err := client.Do(req)
	if err != nil || res.StatusCode != 200 {
		return false // fail open
	}
	defer res.Body.Close()
	var d struct{ IsDisposable bool `json:"is_disposable"` }
	if json.NewDecoder(res.Body).Decode(&d) != nil {
		return false
	}
	return d.IsDisposable
}

// internal/handlers/signup.go
package handlers

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"yourapp/internal/cde"
)

type SignupBody struct {
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required,min=8"`
}

func Signup(c *gin.Context) {
	var body SignupBody
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if cde.IsDisposable(c.Request.Context(), body.Email) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Please use a real email address."})
		return
	}

	// ...create user
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

Notes

Context propagation
Pass `c.Request.Context()` so the API call gets canceled if the client disconnects. Without it, you keep dialing CheckDisposable Email even when nobody's listening.
Reuse the client
The package-level `*http.Client` reuses connections. Don't allocate one per request — Go's HTTP transport is connection-pooled by default.
Other routers
For Echo, swap `c.JSON` for `c.JSON(http.StatusBadRequest, ...)`. For chi/net-http, write the response directly. The `cde.IsDisposable` function is identical.

Get a free API key

500 checks/month, no credit card. No credit card. 30 seconds.

Sign up free →