Project Awesome project awesome

tickstem/verify

Validate email addresses before they hit your database: syntax, MX lookup, disposable domains, and role-based inboxes.

Package 2 stars GitHub

tickstem/verify

Go Reference Go Report Card codecov

Go SDK for Tickstem — email verification for production apps.

Checks syntax, MX records, disposable domains, and role-based prefixes before an address touches your database.

Install

go get github.com/tickstem/verify

Quick start

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/tickstem/verify"
)

func main() {
    client := verify.New(os.Getenv("TICKSTEM_API_KEY"))

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

    fmt.Println(result.Valid)      // true if safe to store
    fmt.Println(result.Disposable) // true if throwaway address
    fmt.Println(result.RoleBased)  // true if generic inbox (admin@, info@, ...)
    fmt.Println(result.Reason)     // explanation when Valid is false
}

Get your API key at app.tickstem.dev.

Usage

Create a client

// Minimal — uses https://api.tickstem.dev/v1
client := verify.New(os.Getenv("TICKSTEM_API_KEY"))

// With options
client := verify.New(apiKey,
    verify.WithBaseURL("http://localhost:8080/v1"),
)

Verify an email

result, err := client.Verify(ctx, "user@example.com")
if err != nil {
    if verify.IsQuotaExceeded(err) {
        // monthly quota hit — upgrade at app.tickstem.dev/dashboard/billing
    }
    log.Fatal(err)
}

if !result.Valid {
    return fmt.Errorf("email not accepted: %s", result.Reason)
}

if result.RoleBased {
    // warn but don't block — some teams share an inbox
}

What gets checked

Check What it catches Why it matters
Syntax Malformed addresses (user@@example, missing TLD) Reject obviously bad input before any network call
MX lookup Domains with no mail server (gmial.com, abandoned domains) Catch typos and dead domains that pass syntax checks
Disposable Throwaway services (Mailinator, Guerrilla Mail, 200+ others) Block single-use signups that inflate user counts and churn immediately
Role-based Generic inboxes (admin@, info@, noreply@, support@, ...) Flag addresses shared by teams or bots — poor engagement, not tied to a real person

No SMTP probing — the recipient mail server is never contacted.

Retrieve history

page, err := client.ListHistory(ctx, verify.ListHistoryParams{
    Limit:  50,
    Offset: 0,
})
for _, v := range page.Verifications {
    fmt.Printf("%s  valid=%v  disposable=%v\n", v.Email, v.Valid, v.Disposable)
}

Error handling

result, err := client.Verify(ctx, email)
if err != nil {
    if verify.IsUnauthorized(err) {
        // invalid or revoked API key
    }
    if verify.IsQuotaExceeded(err) {
        // monthly verification limit reached
    }
    var apiErr *verify.APIError
    if errors.As(err, &apiErr) {
        fmt.Println(apiErr.StatusCode, apiErr.Message)
    }
}

Pricing

Plan Verifications/month Price
Free 500 $0
Starter 5,000 $12/mo
Pro 50,000 $29/mo
Business 500,000 $79/mo

View full pricing →

License

MIT

Back to Go