zerobouncego

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 4, 2023 License: MIT Imports: 17 Imported by: 0

README

Go ZeroBounce API

Go implementation for ZeroBounce Email Validation API v2.

Link to the original repo

Installation and Usage

go get github.com/zerobounce/zerobouncego

This package uses the zero-bounce API which requires an API key. This key can be provide in three ways:

  1. through an environment variable ZERO_BOUNCE_API_KEY (loaded automatically in code)
  2. through an .env file that contains ZERO_BOUNCE_API_KEY and then calling following method before usage:
zerobouncego.ImportApiKeyFromEnvFile()
  1. by settings explicitly in code, using the following method:
zerobouncego.SetApiKey("mysecretapikey")

Generic API methods

package main

import (
	"fmt"
	"time"

	"github.com/zerobounce/zerobouncego"
)

func main() {
	zerobouncego.SetApiKey("... Your API KEY ...")

	// Check your account's credits
	credits, error_ := zerobouncego.GetCredits()
	if error_ != nil {
		fmt.Println("Error from credits: ", error_.Error())
	} else {
		fmt.Println("Credits left:", credits.Credits())
	}

	// Check your account's usage of the API
	start_time := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local)
	end_time := time.Now()
	usage, error_ := zerobouncego.GetApiUsage(start_time, end_time)
	if error_ != nil {
		fmt.Println("Error from API usage: ", error_.Error())
	} else {
		fmt.Println("Total API calls: ", usage.Total)
	}
}

Validation

1. Single email validation
package main

import (
    "fmt"
    "os"
    "github.com/zerobounce/zerobouncego"
)

func main() {

    zerobouncego.APIKey = "... Your API KEY ..."

	// For Querying a single E-Mail and IP
	// IP can also be an empty string
	response, error_ := zerobouncego.Validate("possible_typo@example.com", "123.123.123.123")

	if error_ != nil {
		fmt.Println("error occurred: ", error_.Error())
	} else {
		// Now you can check status
		if response.Status == zerobouncego.S_INVALID {
			fmt.Println("This email is valid")
		}

		// .. or Sub-status
		if response.SubStatus == zerobouncego.SS_POSSIBLE_TYPO {
			fmt.Println("This email might have a typo")
		}
	}
}
2. Batch validation
package main

import (
	"fmt"

	"github.com/zerobounce/zerobouncego"
)

func main() {
	zerobouncego.SetApiKey("... Your API KEY ...")

	emails_to_validate := []zerobouncego.EmailToValidate{
		{EmailAddress: "disposable@example.com", IPAddress: "99.110.204.1"},
		{EmailAddress: "invalid@example.com", IPAddress: "1.1.1.1"},
		{EmailAddress: "valid@example.com"},
		{EmailAddress: "toxic@example.com"},
	}

	response, error_ := zerobouncego.ValidateBatch(emails_to_validate)
	if error_ != nil {
		fmt.Println("error ocurred while batch validating: ", error_.Error())
	} else {
		fmt.Printf("%d successful result fetched and %d error results\n", len(response.EmailBatch), len(response.Errors))
		if len(response.EmailBatch) > 0 {
			fmt.Printf(
				"email '%s' has status '%s' and sub-status '%s'\n",
				response.EmailBatch[0].Address,
				response.EmailBatch[0].Status,
				response.EmailBatch[0].SubStatus,
			)
		}
	}
}
3. Bulk file validation
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/zerobounce/zerobouncego"
)


func main() {
	zerobouncego.SetApiKey("... Your API KEY ...")
	import_file_path := "PATH_TO_CSV_TO_IMPORT"
	result_file_path := "PATH_TO_CSV_TO_EXPORT"

	file, error_ := os.Open(import_file_path)
	if error_ != nil {
		fmt.Println("error while opening the file: ", error_.Error())
		return
	}

	defer file.Close()
	csv_file := zerobouncego.CsvFile{
		File: file, HasHeaderRow: false, EmailAddressColumn: 1, FileName: "emails.csv",
	}
	submit_response, error_ := zerobouncego.BulkValidationSubmit(csv_file, false)
	if error_ != nil {
		fmt.Println("error while submitting data: ", error_.Error())
		return
	}

	fmt.Println("submitted file ID: ", submit_response.FileId)
	var file_status *zerobouncego.FileStatusResponse
	file_status, _ = zerobouncego.BulkValidationFileStatus(submit_response.FileId)
	fmt.Println("file status: ", file_status.FileStatus)
	fmt.Println("completion percentage: ", file_status.Percentage(), "%")

	// wait for the file to get completed
	fmt.Println()
	fmt.Println("Waiting for the file to get completed ")
	var seconds_waited int = 1
	for file_status.Percentage() != 100. {
		time.Sleep(time.Duration(seconds_waited) * time.Second)
		if seconds_waited < 10 {
			seconds_waited += 1
		}

		file_status, error_ = zerobouncego.BulkValidationFileStatus(submit_response.FileId)
		if error_ != nil {
			fmt.Print()
			fmt.Print("error ocurred while polling for status: ", error_.Error())
			return
		}
		fmt.Printf("..%.2f%% ", file_status.Percentage())
	}
	fmt.Println()
	fmt.Println("File validation complete")

	// save validation result
	result_file, error_ := os.OpenFile(result_file_path, os.O_RDWR | os.O_CREATE, 0644)
	if error_ != nil {
		fmt.Println("error on creating result file: ", error_.Error())
		return
	}
	error_ = zerobouncego.BulkValidationResult(submit_response.FileId, result_file)
	defer result_file.Close()
	if error_ != nil {
		fmt.Println("error on fetch validation result: ", error_.Error())
		return
	}
	fmt.Printf("Saved validation result at path: %s\n", result_file_path)

	// delete result file, after saving
	delete_status, error_ := zerobouncego.BulkValidationFileDelete(file_status.FileId)
	if error_ != nil {
		fmt.Println("error on fetch file delete: ", error_.Error())
		return
	}
	fmt.Println(delete_status)
}

Example import file:

disposable@example.com
invalid@example.com
valid@example.com
toxic@example.com

Example export file:

"Email Address","ZB Status","ZB Sub Status","ZB Account","ZB Domain","ZB First Name","ZB Last Name","ZB Gender","ZB Free Email","ZB MX Found","ZB MX Record","ZB SMTP Provider","ZB Did You Mean"
"disposable@example.com","do_not_mail","disposable","","","zero","bounce","male","False","true","mx.example.com","example",""
"invalid@example.com","invalid","mailbox_not_found","","","zero","bounce","male","False","true","mx.example.com","example",""
"valid@example.com","valid","","","","zero","bounce","male","False","true","mx.example.com","example",""
"toxic@example.com","do_not_mail","toxic","","","zero","bounce","male","False","true","mx.example.com","example",""
"mailbox_not_found@example.com","invalid","mailbox_not_found","","","zero","bounce","male","False","true","mx.example.com","example",""
"failed_syntax_check@example.com","invalid","failed_syntax_check","","","zero","bounce","male","False","true","mx.example.com","example",""

4. AI scoring
package main

import (
	"fmt"
	"os"
	"time"

	"github.com/zerobounce/zerobouncego"
)


func main() {
	zerobouncego.SetApiKey("... Your API KEY ...")
	zerobouncego.ImportApiKeyFromEnvFile()
	import_file_path := "./emails.csv"
	result_file_path := "./validation_result.csv"

	file, error_ := os.Open(import_file_path)
	if error_ != nil {
		fmt.Println("error while opening the file: ", error_.Error())
		return
	}

	defer file.Close()
	csv_file := zerobouncego.CsvFile{
		File: file, HasHeaderRow: false, EmailAddressColumn: 1, FileName: "emails.csv",
	}
	submit_response, error_ := zerobouncego.AiScoringFileSubmit(csv_file, false)
	if error_ != nil {
		fmt.Println("error while submitting data: ", error_.Error())
		return
	}

	fmt.Println("submitted file ID: ", submit_response.FileId)
	var file_status *zerobouncego.FileStatusResponse
	file_status, _ = zerobouncego.AiScoringFileStatus(submit_response.FileId)
	fmt.Println("file status: ", file_status.FileStatus)
	fmt.Println("completion percentage: ", file_status.Percentage(), "%")

	// wait for the file to get completed
	fmt.Println()
	fmt.Println("Waiting for the file to get completed ")
	var seconds_waited int = 1
	for file_status.Percentage() != 100. {
		time.Sleep(time.Duration(seconds_waited) * time.Second)
		if seconds_waited < 10 {
			seconds_waited += 1
		}

		file_status, error_ = zerobouncego.AiScoringFileStatus(submit_response.FileId)
		if error_ != nil {
			fmt.Print()
			fmt.Print("error ocurred while polling for status: ", error_.Error())
			return
		}
		fmt.Printf("..%.2f%% ", file_status.Percentage())
	}
	fmt.Println()
	fmt.Println("File validation complete")

	// save validation result
	result_file, error_ := os.OpenFile(result_file_path, os.O_RDWR | os.O_CREATE, 0644)
	if error_ != nil {
		fmt.Println("error on creating result file: ", error_.Error())
		return
	}
	error_ = zerobouncego.AiScoringResult(submit_response.FileId, result_file)
	defer result_file.Close()
	if error_ != nil {
		fmt.Println("error on fetch validation result: ", error_.Error())
		return
	}
	fmt.Printf("Saved validation result at path: %s\n", result_file_path)

	// delete result file, after saving
	delete_status, error_ := zerobouncego.AiScoringFileDelete(file_status.FileId)
	if error_ != nil {
		fmt.Println("error on fetch file delete: ", error_.Error())
		return
	}
	fmt.Println(delete_status)
}

Example import file:

disposable@example.com
invalid@example.com
valid@example.com
toxic@example.com

Example export file:

"Email Address","ZeroBounceQualityScore"
"disposable@example.com","0"
"invalid@example.com","10"
"valid@example.com","10"
"toxic@example.com","2"

Email Finder

Email Finder allows you to search for new business email addresses using our proprietary technologies

1. Single Email finder
package main

import (
	"fmt"

	"github.com/zerobounce/zerobouncego"
)

func main() {
	zerobouncego.SetApiKey("... Your API KEY ...")

	response, error_ := zerobouncego.FindEmail("example.com", "John", "", "Doe")
	if error_ != nil {
		fmt.Println(error_.Error())
		return
	}
	fmt.Println(response)
}
2. Single domain finder
package main

import (
	"fmt"

	"github.com/zerobounce/zerobouncego"
)

func main() {
	zerobouncego.SetApiKey("... Your API KEY ...")
	response, error_ := zerobouncego.DomainSearch("example.com")
	if error_ != nil {
		fmt.Println(error_.Error())
		return
	}
	fmt.Println(response)
}

Testing

This package contains both unit tests and integration tests (which are excluded from the test suite). Unit test files are the ones ending in "_test.go" (as go requires) and the integration tests are ending in ("_integration_t.go").

In order to run the integration tests:

  • set appropriate ZERO_BOUNCE_API_KEY environment variable
  • rename all "_integration_t.go" into "_integration_test.go"
  • run either individual or all tests (go test .)

NOTE: currently, the unit tests can be updated such that, by removing the mocking and explicit API key setting, they should work as integration tests as well AS LONG AS a valid API key is provided via environment

Documentation

Index

Constants

View Source
const (
	CONTENT_TYPE_OCTET_STREAM = "application/octet-stream"
	CONTENT_TYPE_JSON         = "application/json"
)
View Source
const (
	URI                     = `https://api.zerobounce.net/v2/`
	BULK_URI                = `https://bulkapi.zerobounce.net/v2/`
	ENDPOINT_CREDITS        = "/getcredits"
	ENDPOINT_ACTIVITY_DATA  = "/activity"
	ENDPOINT_VALIDATE       = "/validate"
	ENDPOINT_API_USAGE      = "/getapiusage"
	ENDPOINT_BATCH_VALIDATE = "/validatebatch"
	ENDPOINT_FILE_SEND      = "/sendfile"
	ENDPOINT_FILE_STATUS    = "/filestatus"
	ENDPOINT_FILE_RESULT    = "/getfile" // Content-type: application/octet-stream
	ENDPOINT_FILE_DELETE    = "/deletefile"
	ENDPOINT_SCORING_SEND   = "/scoring/sendfile"
	ENDPOINT_SCORING_STATUS = "/scoring/filestatus"
	ENDPOINT_SCORING_RESULT = "/scoring/getfile" // Content-type: application/octet-stream
	ENDPOINT_SCORING_DELETE = "/scoring/deletefile"
	ENDPOINT_EMAIL_FINDER   = "/guessformat"
	SANDBOX_IP              = "99.110.204.1"
)
View Source
const (
	DATE_TIME_FORMAT = "2006-01-02 15:04:05"
	DATE_ONLY_FORMAT = "2006-01-02"
)
View Source
const (
	S_VALID       = "valid"
	S_INVALID     = "invalid"
	S_CATCH_ALL   = "catch-all"
	S_UNKNOWN     = "unknown"
	S_SPAMTRAP    = "spamtrap"
	S_ABUSE       = "abuse"
	S_DO_NOT_MAIL = "do_not_mail"
)

validation statuses

View Source
const (
	SS_ANTISPAM_SYSTEM             = "antispam_system"
	SS_GREYLISTED                  = "greylisted"
	SS_MAIL_SERVER_TEMPORARY_ERROR = "mail_server_temporary_error"
	SS_FORCIBLE_DISCONNECT         = "forcible_disconnect"
	SS_MAIL_SERVER_DID_NOT_RESPOND = "mail_server_did_not_respond"
	SS_TIMEOUT_EXCEEDED            = "timeout_exceeded"
	SS_FAILED_SMTP_CONNECTION      = "failed_smtp_connection"
	SS_MAILBOX_QUOTA_EXCEEDED      = "mailbox_quota_exceeded"
	SS_EXCEPTION_OCCURRED          = "exception_occurred"
	SS_POSSIBLE_TRAP               = "possible_trap"
	SS_ROLE_BASED                  = "role_based"
	SS_GLOBAL_SUPPRESSION          = "global_suppression"
	SS_MAILBOX_NOT_FOUND           = "mailbox_not_found"
	SS_NO_DNS_ENTRIES              = "no_dns_entries"
	SS_FAILED_SYNTAX_CHECK         = "failed_syntax_check"
	SS_POSSIBLE_TYPO               = "possible_typo"
	SS_UNROUTABLE_IP_ADDRESS       = "unroutable_ip_address"
	SS_LEADING_PERIOD_REMOVED      = "leading_period_removed"
	SS_DOES_NOT_ACCEPT_MAIL        = "does_not_accept_mail"
	SS_ALIAS_ADDRESS               = "alias_address"
	SS_ROLE_BASED_CATCH_ALL        = "role_based_catch_all"
	SS_DISPOSABLE                  = "disposable"
	SS_TOXIC                       = "toxic"
)

validation sub statuses

Variables

View Source
var API_KEY string = os.Getenv("ZERO_BOUNCE_API_KEY")

API_KEY the API key used in order to make the requests

View Source
var MOCK_VALIDATE_RESPONSE = map[string]string{
	"disposable@example.com": `{
		"address": "disposable@example.com",
		"status": "do_not_mail",
		"sub_status": "disposable",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:27.816"
	}`,
	"invalid@example.com": `{
		"address": "invalid@example.com",
		"status": "invalid",
		"sub_status": "mailbox_not_found",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.003"
	}`,
	"valid@example.com": `{
		"address": "valid@example.com",
		"status": "valid",
		"sub_status": "",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.105"
	}`,
	"toxic@example.com": `{
		"address": "toxic@example.com",
		"status": "do_not_mail",
		"sub_status": "toxic",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.210"
	}`,
	"donotmail@example.com": `{
		"address": "donotmail@example.com",
		"status": "do_not_mail",
		"sub_status": "role_based",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.329"
	}`,
	"spamtrap@example.com": `{
		"address": "spamtrap@example.com",
		"status": "spamtrap",
		"sub_status": "",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.380"
	}`,
	"abuse@example.com": `{
		"address": "abuse@example.com",
		"status": "abuse",
		"sub_status": "",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.585"
	}`,
	"catch_all@example.com": `{
		"address": "catch_all@example.com",
		"status": "catch-all",
		"sub_status": "",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.639"
	}`,
	"antispam_system@example.com": `{
		"address": "antispam_system@example.com",
		"status": "unknown",
		"sub_status": "antispam_system",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.767"
	}`,
	"does_not_accept_mail@example.com": `{
		"address": "does_not_accept_mail@example.com",
		"status": "invalid",
		"sub_status": "does_not_accept_mail",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.929"
	}`,
	"exception_occurred@example.com": `{
		"address": "exception_occurred@example.com",
		"status": "unknown",
		"sub_status": "exception_occurred",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:28.971"
	}`,
	"failed_smtp_connection@example.com": `{
		"address": "failed_smtp_connection@example.com",
		"status": "unknown",
		"sub_status": "failed_smtp_connection",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:29.144"
	}`,
	"failed_syntax_check@example.com": `{
		"address": "failed_syntax_check@example.com",
		"status": "invalid",
		"sub_status": "failed_syntax_check",
		"free_email": false,
		"did_you_mean": null,
		"account": "",
		"domain": "",
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:29.312"
	}`,
	"forcible_disconnect@example.com": `{
		"address": "forcible_disconnect@example.com",
		"status": "unknown",
		"sub_status": "forcible_disconnect",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:29.932"
	}`,
	"global_suppression@example.com": `{
		"address": "global_suppression@example.com",
		"status": "do_not_mail",
		"sub_status": "global_suppression",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:30.208"
	}`,
	"greylisted@example.com": `{
		"address": "greylisted@example.com",
		"status": "unknown",
		"sub_status": "greylisted",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:30.502"
	}`,
	"leading_period_removed@example.com": `{
		"address": "leading_period_removed@example.com",
		"status": "valid",
		"sub_status": "leading_period_removed",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:30.742"
	}`,
	"mail_server_did_not_respond@example.com": `{
		"address": "mail_server_did_not_respond@example.com",
		"status": "unknown",
		"sub_status": "mail_server_did_not_respond",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:30.854"
	}`,
	"mail_server_temporary_error@example.com": `{
		"address": "mail_server_temporary_error@example.com",
		"status": "unknown",
		"sub_status": "mail_server_temporary_error",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:30.913"
	}`,
	"mailbox_quota_exceeded@example.com": `{
		"address": "mailbox_quota_exceeded@example.com",
		"status": "invalid",
		"sub_status": "mailbox_quota_exceeded",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.084"
	}`,
	"mailbox_not_found@example.com": `{
		"address": "mailbox_not_found@example.com",
		"status": "invalid",
		"sub_status": "mailbox_not_found",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.153"
	}`,
	"no_dns_entries@example.com": `{
		"address": "no_dns_entries@example.com",
		"status": "invalid",
		"sub_status": "no_dns_entries",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.225"
	}`,
	"possible_trap@example.com": `{
		"address": "possible_trap@example.com",
		"status": "do_not_mail",
		"sub_status": "possible_trap",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.453"
	}`,
	"possible_typo@example.com": `{
		"address": "possible_typo@example.com",
		"status": "invalid",
		"sub_status": "possible_typo",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.537"
	}`,
	"role_based@example.com": `{
		"address": "role_based@example.com",
		"status": "do_not_mail",
		"sub_status": "role_based",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.679"
	}`,
	"timeout_exceeded@example.com": `{
		"address": "timeout_exceeded@example.com",
		"status": "unknown",
		"sub_status": "timeout_exceeded",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.810"
	}`,
	"unroutable_ip_address@example.com": `{
		"address": "unroutable_ip_address@example.com",
		"status": "invalid",
		"sub_status": "unroutable_ip_address",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:32.040"
	}`,
	"free_email@example.com": `{
		"address": "free_email@example.com",
		"status": "valid",
		"sub_status": "",
		"free_email": true,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:32.095"
	}`,
	"role_based_catch_all@example.com": `{
		"address": "role_based_catch_all@example.com",
		"status": "do_not_mail",
		"sub_status": "role_based_catch_all",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:32.251"
	}`,
	"unknown@example.com": `{
		"address": "unknown@example.com",
		"status": "unknown",
		"sub_status": "mail_server_temporary_error",
		"free_email": false,
		"did_you_mean": null,
		"account": null,
		"domain": null,
		"domain_age_days": "9692",
		"smtp_provider": "example",
		"mx_found": "true",
		"mx_record": "mx.example.com",
		"firstname": "zero",
		"lastname": "bounce",
		"gender": "male",
		"country": "United States",
		"region": "Florida",
		"city": "West Palm Beach",
		"zipcode": "33401",
		"processed_at": "2023-03-23 12:30:31.961"
	}`,
}

Functions

func AiScoringResult

func AiScoringResult(file_id string, file_writer io.Writer) error

AiScoringResult - save a csv containing the results of the file previously sent, that corresponds to the given file ID parameter

func BulkValidationResult

func BulkValidationResult(file_id string, file_writer io.Writer) error

BulkValidationResult - save a csv containing the results of the file with the given file ID

func DoGetRequest

func DoGetRequest(url string, object APIResponse) error

DoGetRequest does a GET request to the API

func ErrorFromResponse

func ErrorFromResponse(response *http.Response) error

ErrorFromResponse given a response who is expected to have a json structure, generate a joined response of all values within that json This function was done because error messages have inconsistent keys eg: error, message, Message etc

func GenericResultFetch

func GenericResultFetch(file_id, endpoint string, file_writer io.Writer) error

GenericResultFetch - save a csv containing the results of the file with the given file ID

func ImportApiKeyFromEnvFile

func ImportApiKeyFromEnvFile() bool

ImportApiKeyFromEnvFile provided that a .env file can be found where the program is running, load it, extract the API key and set it

func PrepareURL

func PrepareURL(endpoint string, params url.Values) (string, error)

PrepareURL prepares the URL for a get request by attaching both the API key and the given params

func SetApiKey

func SetApiKey(new_api_key_value string)

SetApiKey set the API key explicitly

func TestBulkEmailValidation

func TestBulkEmailValidation(t *testing.T)

func TestInvalidApiKey

func TestInvalidApiKey(t *testing.T)

TestInvalidApiKey test expecting one error, relevant to invalid API key

func TestValidate

func TestValidate(t *testing.T)

Types

type APIResponse

type APIResponse interface{}

APIResponse basis for api responses

type ActivityDataResponse

type ActivityDataResponse struct {
	Found           bool        `json:"found"`
	ActiveInDaysRaw null.String `json:"active_in_days"`
}

func GetActivityData

func GetActivityData(email_address string) (*ActivityDataResponse, error)

GetActivityData check the activity of an email address

func (ActivityDataResponse) ActiveInDays

func (a ActivityDataResponse) ActiveInDays() int

type ApiUsageResponse

type ApiUsageResponse struct {
	// Total number of times the API has been called
	Total int `json:"total"`
	// Total valid email addresses returned by the API
	StatusValid int `json:"status_valid"`
	// Total invalid email addresses returned by the API
	StatusInvalid int `json:"status_invalid"`
	// Total catch-all email addresses returned by the API
	StatusCatchAll int `json:"status_catch_all"`
	// Total do not mail email addresses returned by the API
	StatusDoNotMail int `json:"status_do_not_mail"`
	// Total spamtrap email addresses returned by the API
	StatusSpamtrap int `json:"status_spamtrap"`
	// Total unknown email addresses returned by the API
	StatusUnknown int `json:"status_unknown"`
	// Total number of times the API has a sub status of "toxic"
	SubStatusToxic int `json:"sub_status_toxic"`
	// Total number of times the API has a sub status of "disposable"
	SubStatusDisposable int `json:"sub_status_disposable"`
	// Total number of times the API has a sub status of "role_based"
	SubStatusRoleBased int `json:"sub_status_role_based"`
	// Total number of times the API has a sub status of "possible_trap"
	SubStatusPossibleTrap int `json:"sub_status_possible_trap"`
	// Total number of times the API has a sub status of "global_suppression"
	SubStatusGlobalSuppression int `json:"sub_status_global_suppression"`
	// Total number of times the API has a sub status of "timeout_exceeded"
	SubStatusTimeoutExceeded int `json:"sub_status_timeout_exceeded"`
	// Total number of times the API has a sub status of "mail_server_temporary_error"
	SubStatusMailServerTemporaryError int `json:"sub_status_mail_server_temporary_error"`
	// Total number of times the API has a sub status of "mail_server_did_not_respond"
	SubStatusMailServerDidNotRespond int `json:"sub_status_mail_server_did_not_respond"`
	// Total number of times the API has a sub status of "greylisted"
	SubStatusGreylisted int `json:"sub_status_greylisted"`
	// Total number of times the API has a sub status of "antispam_system"
	SubStatusAntispamSystem int `json:"sub_status_antispam_system"`
	// Total number of times the API has a sub status of "does_not_accept_mail"
	SubStatusDoesNotAcceptMail int `json:"sub_status_does_not_accept_mail"`
	// Total number of times the API has a sub status of "exception_occurred"
	SubStatusExceptionOccurred int `json:"sub_status_exception_occurred"`
	// Total number of times the API has a sub status of "failed_syntax_check"
	SubStatusFailedSyntaxCheck int `json:"sub_status_failed_syntax_check"`
	// Total number of times the API has a sub status of "mailbox_not_found"
	SubStatusMailboxNotFound int `json:"sub_status_mailbox_not_found"`
	// Total number of times the API has a sub status of "unroutable_ip_address"
	SubStatusUnroutableIpAddress int `json:"sub_status_unroutable_ip_address"`
	// Total number of times the API has a sub status of "possible_typo"
	SubStatusPossibleTypo int `json:"sub_status_possible_typo"`
	// Total number of times the API has a sub status of "no_dns_entries"
	SubStatusNoDnsEntries int `json:"sub_status_no_dns_entries"`
	// Total role based catch alls the API has a sub status of "role_based_catch_all"
	SubStatusRoleBasedCatchAll int `json:"sub_status_role_based_catch_all"`
	// Total number of times the API has a sub status of "mailbox_quota_exceeded"
	SubStatusMailboxQuotaExceeded int `json:"sub_status_mailbox_quota_exceeded"`
	// Total forcible disconnects the API has a sub status of "forcible_disconnect"
	SubStatusForcibleDisconnect int `json:"sub_status_forcible_disconnect"`
	// Total failed SMTP connections the API has a sub status of "failed_smtp_connection"
	SubStatusFailedSmtpConnection int `json:"sub_status_failed_smtp_connection"`
	// Total number times the API has a sub status "mx_forward"
	SubStatusMxForward int `json:"sub_status_mx_forward"`
	// Start date of query.
	RawStartDate string `json:"start_date"`
	// End date of query.
	RawEndDate string `json:"end_date"`
}

ApiUsageResponse response structure for the API usage functionality

func GetApiUsage

func GetApiUsage(start_date, end_date time.Time) (*ApiUsageResponse, error)

GetApiUsage the usage of the API within a date interval

func (ApiUsageResponse) EndDate

func (v ApiUsageResponse) EndDate() (time.Time, error)

StartDate provide the parsed end date of an API usage response

func (ApiUsageResponse) StartDate

func (v ApiUsageResponse) StartDate() (time.Time, error)

StartDate provide the parsed start date of an API usage response

type CreditsResponse

type CreditsResponse struct {
	CreditsRaw string `json:"Credits"`
}

CreditsResponse response of the credits balance

func GetCredits

func GetCredits() (*CreditsResponse, error)

GetCredits gets credits balance

func (*CreditsResponse) Credits

func (c *CreditsResponse) Credits() int

type CsvFile

type CsvFile struct {
	File         io.Reader `json:"file"`
	FileName     string    `json:"file_name"`
	HasHeaderRow bool      `json:"has_header_row"`

	// column index starts from 1
	// if either of the following will be 0, will be excluded from the request
	EmailAddressColumn int `json:"email_address_column"`
	FirstNameColumn    int `json:"first_name_column"`
	LastNameColumn     int `json:"last_name_column"`
	GenderColumn       int `json:"gender_column"`
	IpAddressColumn    int `json:"ip_address_column"`
}

CsvFile - used for bulk validations and AI scoring

func ImportCsvFile

func ImportCsvFile(path_to_file string, has_header bool, email_column int) (*CsvFile, error)

ImportCsvFile - import a file to be uploaded for validation

func (*CsvFile) ColumnsMapping

func (c *CsvFile) ColumnsMapping() map[string]int

ColumnsMapping - function generating how columns-index mapping of the instance

func (*CsvFile) FillMultipartForm

func (csv_file *CsvFile) FillMultipartForm(multipart_writer *multipart.Writer) error

FillMultipartForm - populate a multi-part form with the data contained within current `CsvFile` instance

type DomainFormats added in v1.0.1

type DomainFormats struct {
	Format     string `json:"format"`
	Confidence string `json:"confidence"`
}

DomainFormats part of the `FindEmailResponse` describing other domain formats

type EmailBatchError

type EmailBatchError struct {
	Error        string `json:"error"`
	EmailAddress string `json:"email_address"`
}

EmailBatchError an error unit received in the response, that can be associated with an email sent to the batch validate endpoint

type EmailToValidate

type EmailToValidate struct {
	EmailAddress string `json:"email_address"`
	IPAddress    string `json:"ip_address"`
}

EmailToValidate represents one unit send to the batch validate endpoint

func EmailsToValidate

func EmailsToValidate() []EmailToValidate

type FileStatusResponse

type FileStatusResponse struct {
	Success            bool   `json:"success"`
	FileId             string `json:"file_id"`
	FileName           string `json:"file_name"`
	UploadDateRaw      string `json:"upload_date"`
	FileStatus         string `json:"file_status"`
	CompletePercentage string `json:"complete_percentage"`
	ReturnUrl          string `json:"return_url"`
}

BulkValidationFileStatus - response payload after a file status check

func AiScoringFileStatus

func AiScoringFileStatus(file_id string) (*FileStatusResponse, error)

BulkValidationFileStatus - check the percentage of completion of a file uploaded for AI scoring

func BulkValidationFileStatus

func BulkValidationFileStatus(file_id string) (*FileStatusResponse, error)

BulkValidationFileStatus - check the percentage of completion of a file uploaded for bulk validation

func GenericFileStatusCheck

func GenericFileStatusCheck(file_id, endpoint string) (*FileStatusResponse, error)

GenericFileStatusCheck - check the percentage of completion of a file uploaded for the operation represented by the given endpoint

func (*FileStatusResponse) Percentage

func (b *FileStatusResponse) Percentage() float64

Percentage - provide the percentage, from a response payload, as a float

func (*FileStatusResponse) UploadDate

func (b *FileStatusResponse) UploadDate() (time.Time, error)

UploadDate - provide the upload date, from a response payload, as a time.Time

type FileValidationResponse

type FileValidationResponse struct {
	Success  bool        `json:"success"`
	Message  interface{} `json:"message"`
	FileName string      `json:"file_name"`
	FileId   string      `json:"file_id"`
}

FileValidationResponse - response payload from a successful

func AiScoringFileDelete

func AiScoringFileDelete(file_id string) (*FileValidationResponse, error)

AiScoringFileDelete - delete the result file associated with a file ID

func AiScoringFileSubmit

func AiScoringFileSubmit(csv_file CsvFile, remove_duplicate bool) (*FileValidationResponse, error)

AiScoringSubmit - submit a file with emails for AI scoring

func BulkValidationFileDelete

func BulkValidationFileDelete(file_id string) (*FileValidationResponse, error)

BulkValidationFileDelete - delete the result file associated with a file ID

func BulkValidationSubmit

func BulkValidationSubmit(csv_file CsvFile, remove_duplicate bool) (*FileValidationResponse, error)

BulkValidationSubmit - submit a file with emails for validation

func GenericFileDelete

func GenericFileDelete(file_id, endpoint string) (*FileValidationResponse, error)

GenericFileDelete - delete the result file associated with a file ID

func GenericFileSubmit

func GenericFileSubmit(
	csv_file CsvFile,
	remove_duplicate bool,
	endpoint string,
) (*FileValidationResponse, error)

GenericFileSubmit - submits a csv file to an operation represented by the given endpoint

type FindEmailResponse added in v1.0.1

type FindEmailResponse struct {
	Email              string          `json:"email"`
	Domain             string          `json:"domain"`
	Format             string          `json:"format"`
	Status             string          `json:"status"`
	SubStatus          string          `json:"sub_status"`
	Confidence         string          `json:"confidence"`
	DidYouMean         string          `json:"did_you_mean"`
	FailureReason      string          `json:"failure_reason"`
	OtherDomainFormats []DomainFormats `json:"other_domain_formats"`
}

FindEmailResponse response structure for Find Email API `Confidence` field possible values: low, medium, high, unknown, undetermined (it is inconsistent as it can be either lowercase or uppercase)

func DomainSearch added in v1.0.1

func DomainSearch(domain string) (*FindEmailResponse, error)

DomainSearch - attempts to detect possible patterns a specific company uses

func FindEmail added in v1.0.1

func FindEmail(domain, first_name, middle_name, last_name string) (*FindEmailResponse, error)

FindEmail uses parameters to provide valid business email

type SingleTest

type SingleTest struct {
	Email     string
	Status    string
	SubStatus string
	FreeEmail bool
}

TESTING

type ValidateBatchResponse

type ValidateBatchResponse struct {
	EmailBatch []ValidateResponse `json:"email_batch"`
	Errors     []EmailBatchError  `json:"errors"`
}

ValidateBatchResponse represents the structure of a 200OK batch validate response

func ValidateBatch

func ValidateBatch(emails_list []EmailToValidate) (ValidateBatchResponse, error)

ValidateBatch given a list of emails (and, optionally, their IPs), validate them and return both validation details and errors about the emails sent

type ValidateResponse

type ValidateResponse struct {
	Address        string      `json:"address"`
	Status         string      `json:"status"`
	SubStatus      string      `json:"sub_status"`
	FreeEmail      bool        `json:"free_email"`
	DidYouMean     null.String `json:"did_you_mean"`
	Account        string      `json:"account"`
	Domain         string      `json:"domain"`
	DomainAgeDays  null.String `json:"domain_age_days"`
	SMTPProvider   null.String `json:"smtp_provider"`
	MxRecord       string      `json:"mx_record"`
	MxFound        string      `json:"mx_found"`
	Firstname      null.String `json:"firstname"`
	Lastname       null.String `json:"lastname"`
	Gender         null.String `json:"gender"`
	Country        null.String `json:"country"`
	Region         null.String `json:"region"`
	City           null.String `json:"city"`
	Zipcode        null.String `json:"zipcode"`
	RawProcessedAt string      `json:"processed_at"`
}

ValidateResponse response structure for single email validation

func Validate

func Validate(email string, IPAddress string) (*ValidateResponse, error)

Validate validates a single email

func (*ValidateResponse) IsValid

func (v *ValidateResponse) IsValid() bool

IsValid checks if an email is valid

func (ValidateResponse) ProcessedAt

func (v ValidateResponse) ProcessedAt() (time.Time, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL