172 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package mailgun
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/pkg/errors"
 | |
| )
 | |
| 
 | |
| // The EmailVerificationParts structure breaks out the basic elements of an email address.
 | |
| // LocalPart includes everything up to the '@' in an e-mail address.
 | |
| // Domain includes everything after the '@'.
 | |
| // DisplayName is no longer used, and will appear as "".
 | |
| type EmailVerificationParts struct {
 | |
| 	LocalPart   string `json:"local_part"`
 | |
| 	Domain      string `json:"domain"`
 | |
| 	DisplayName string `json:"display_name"`
 | |
| }
 | |
| 
 | |
| // EmailVerification records basic facts about a validated e-mail address.
 | |
| // See the ValidateEmail method and example for more details.
 | |
| //
 | |
| type EmailVerification struct {
 | |
| 	// Indicates whether an email address conforms to IETF RFC standards.
 | |
| 	IsValid bool `json:"is_valid"`
 | |
| 	// Indicates whether an email address is deliverable.
 | |
| 	MailboxVerification string `json:"mailbox_verification"`
 | |
| 	// Parts records the different subfields of the parsed email address
 | |
| 	Parts EmailVerificationParts `json:"parts"`
 | |
| 	// Echoes the address provided.
 | |
| 	Address string `json:"address"`
 | |
| 	// Provides a simple recommendation in case the address is invalid or
 | |
| 	// Mailgun thinks you might have a typo. May be empty, in which case
 | |
| 	// Mailgun has no recommendation to give.
 | |
| 	DidYouMean string `json:"did_you_mean"`
 | |
| 	// Indicates whether Mailgun thinks the address is from a known
 | |
| 	// disposable mailbox provider.
 | |
| 	IsDisposableAddress bool `json:"is_disposable_address"`
 | |
| 	// Indicates whether Mailgun thinks the address is an email distribution list.
 | |
| 	IsRoleAddress bool `json:"is_role_address"`
 | |
| 	// A human readable reason the address is reported as invalid
 | |
| 	Reason string `json:"reason"`
 | |
| }
 | |
| 
 | |
| type addressParseResult struct {
 | |
| 	Parsed      []string `json:"parsed"`
 | |
| 	Unparseable []string `json:"unparseable"`
 | |
| }
 | |
| 
 | |
| type EmailValidator interface {
 | |
| 	ValidateEmail(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error)
 | |
| 	ParseAddresses(ctx context.Context, addresses ...string) ([]string, []string, error)
 | |
| }
 | |
| 
 | |
| type EmailValidatorImpl struct {
 | |
| 	client      *http.Client
 | |
| 	isPublicKey bool
 | |
| 	apiBase     string
 | |
| 	apiKey      string
 | |
| }
 | |
| 
 | |
| // Creates a new validation instance.
 | |
| // * If a public key is provided, uses the public validation endpoints
 | |
| // * If a private key is provided, uses the private validation endpoints
 | |
| func NewEmailValidator(apiKey string) *EmailValidatorImpl {
 | |
| 	isPublicKey := false
 | |
| 
 | |
| 	// Did the user pass in a public key?
 | |
| 	if strings.HasPrefix(apiKey, "pubkey-") {
 | |
| 		isPublicKey = true
 | |
| 	}
 | |
| 
 | |
| 	return &EmailValidatorImpl{
 | |
| 		client:      http.DefaultClient,
 | |
| 		isPublicKey: isPublicKey,
 | |
| 		apiBase:     APIBase,
 | |
| 		apiKey:      apiKey,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewEmailValidatorFromEnv returns a new EmailValidator using environment variables
 | |
| // If MG_PUBLIC_API_KEY is set, assume using the free validation subject to daily usage limits
 | |
| // If only MG_API_KEY is set, assume using the /private validation routes with no daily usage limits
 | |
| func NewEmailValidatorFromEnv() (*EmailValidatorImpl, error) {
 | |
| 	apiKey := os.Getenv("MG_PUBLIC_API_KEY")
 | |
| 	if apiKey == "" {
 | |
| 		apiKey = os.Getenv("MG_API_KEY")
 | |
| 		if apiKey == "" {
 | |
| 			return nil, errors.New(
 | |
| 				"environment variable MG_PUBLIC_API_KEY or MG_API_KEY required for email validation")
 | |
| 		}
 | |
| 	}
 | |
| 	v := NewEmailValidator(apiKey)
 | |
| 	url := os.Getenv("MG_URL")
 | |
| 	if url != "" {
 | |
| 		v.SetAPIBase(url)
 | |
| 	}
 | |
| 	return v, nil
 | |
| }
 | |
| 
 | |
| // APIBase returns the API Base URL configured for this client.
 | |
| func (m *EmailValidatorImpl) APIBase() string {
 | |
| 	return m.apiBase
 | |
| }
 | |
| 
 | |
| // SetAPIBase updates the API Base URL for this client.
 | |
| func (m *EmailValidatorImpl) SetAPIBase(address string) {
 | |
| 	m.apiBase = address
 | |
| }
 | |
| 
 | |
| // SetClient updates the HTTP client for this client.
 | |
| func (m *EmailValidatorImpl) SetClient(c *http.Client) {
 | |
| 	m.client = c
 | |
| }
 | |
| 
 | |
| // Client returns the HTTP client configured for this client.
 | |
| func (m *EmailValidatorImpl) Client() *http.Client {
 | |
| 	return m.client
 | |
| }
 | |
| 
 | |
| // APIKey returns the API key used for validations
 | |
| func (m *EmailValidatorImpl) APIKey() string {
 | |
| 	return m.apiKey
 | |
| }
 | |
| 
 | |
| func (m *EmailValidatorImpl) getAddressURL(endpoint string) string {
 | |
| 	if m.isPublicKey {
 | |
| 		return fmt.Sprintf("%s/address/%s", m.APIBase(), endpoint)
 | |
| 	}
 | |
| 	return fmt.Sprintf("%s/address/private/%s", m.APIBase(), endpoint)
 | |
| }
 | |
| 
 | |
| // ValidateEmail performs various checks on the email address provided to ensure it's correctly formatted.
 | |
| // It may also be used to break an email address into its sub-components.  (See example.)
 | |
| func (m *EmailValidatorImpl) ValidateEmail(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) {
 | |
| 	r := newHTTPRequest(m.getAddressURL("validate"))
 | |
| 	r.setClient(m.Client())
 | |
| 	r.addParameter("address", email)
 | |
| 	if mailBoxVerify {
 | |
| 		r.addParameter("mailbox_verification", "true")
 | |
| 	}
 | |
| 	r.setBasicAuth(basicAuthUser, m.APIKey())
 | |
| 
 | |
| 	var response EmailVerification
 | |
| 	err := getResponseFromJSON(ctx, r, &response)
 | |
| 	if err != nil {
 | |
| 		return EmailVerification{}, err
 | |
| 	}
 | |
| 
 | |
| 	return response, nil
 | |
| }
 | |
| 
 | |
| // ParseAddresses takes a list of addresses and sorts them into valid and invalid address categories.
 | |
| // NOTE: Use of this function requires a proper public API key.  The private API key will not work.
 | |
| func (m *EmailValidatorImpl) ParseAddresses(ctx context.Context, addresses ...string) ([]string, []string, error) {
 | |
| 	r := newHTTPRequest(m.getAddressURL("parse"))
 | |
| 	r.setClient(m.Client())
 | |
| 	r.addParameter("addresses", strings.Join(addresses, ","))
 | |
| 	r.setBasicAuth(basicAuthUser, m.APIKey())
 | |
| 
 | |
| 	var response addressParseResult
 | |
| 	err := getResponseFromJSON(ctx, r, &response)
 | |
| 	if err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 
 | |
| 	return response.Parsed, response.Unparseable, nil
 | |
| }
 |