Repository: mailgun/mailgun-go
Pull request #379 (2025-01-06 18:15:14)

DE-1394 Removed deprecated v3 validation fields


Patch:
diff --git a/email_validation.go b/email_validation.go
index 123e3ce..3589f81 100644
--- a/email_validation.go
+++ b/email_validation.go
@@ -9,78 +9,50 @@ import (
 	"github.com/mailgun/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.
-// TODO(v5): remove /v3 validations fields(Reason)
 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"`
-	// The reason why a specific validation may be unsuccessful. (Available in the V3 response)
-	Reason string `json:"reason"`
+
 	// A list of potential reasons why a specific validation may be unsuccessful. (Available in the v4 response)
-	Reasons []string
-	// Risk assessment for the provided email.
-	Risk string `json:"risk"`
+	Reason []string `json:"reason"`
+
 	// Result
 	Result string `json:"result"`
+
+	// Risk assessment for the provided email.
+	Risk string `json:"risk"`
+
+	LastSeen int64 `json:"last_seen,omitempty"`
+
+	// 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,omitempty"`
+
 	// Engagement results are a macro-level view that explain an email recipient’s propensity to engage.
 	// https://documentation.mailgun.com/docs/inboxready/mailgun-validate/validate_engagement/
 	Engagement *EngagementData `json:"engagement,omitempty"`
+
+	RootAddress string `json:"root_address,omitempty"`
 }
 
 type EngagementData struct {
 	Engaging bool   `json:"engaging"`
-	Behavior string `json:"behavior,omitempty"`
 	IsBot    bool   `json:"is_bot"`
-}
-
-type v4EmailValidationResp struct {
-	IsValid             bool                   `json:"is_valid"`
-	MailboxVerification string                 `json:"mailbox_verification"`
-	Parts               EmailVerificationParts `json:"parts"`
-	Address             string                 `json:"address"`
-	DidYouMean          string                 `json:"did_you_mean"`
-	IsDisposableAddress bool                   `json:"is_disposable_address"`
-	IsRoleAddress       bool                   `json:"is_role_address"`
-	Reason              []string               `json:"reason"`
-	Risk                string                 `json:"risk"`
-	Result              string                 `json:"result"`
-	Engagement          *EngagementData        `json:"engagement,omitempty"`
-}
-
-type addressParseResult struct {
-	Parsed      []string `json:"parsed"`
-	Unparseable []string `json:"unparseable"`
+	Behavior string `json:"behavior,omitempty"`
 }
 
 type EmailValidator interface {
 	ValidateEmail(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error)
-	ParseAddresses(ctx context.Context, addresses ...string) ([]string, []string, error)
 }
 
 // TODO(v5): switch to MailgunImpl
@@ -148,10 +120,6 @@ func (m *EmailValidatorImpl) APIKey() string {
 // It may also be used to break an email address into its sub-components. If user has set the
 // TODO(v5): move to *MailgunImpl?
 func (m *EmailValidatorImpl) ValidateEmail(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) {
-	return m.validateV4(ctx, email, mailBoxVerify)
-}
-
-func (m *EmailValidatorImpl) validateV4(ctx context.Context, email string, mailBoxVerify bool) (EmailVerification, error) {
 	r := newHTTPRequest(fmt.Sprintf("%s/v4/address/validate", m.APIBase()))
 	r.setClient(m.Client())
 	r.addParameter("address", email)
@@ -160,22 +128,10 @@ func (m *EmailValidatorImpl) validateV4(ctx context.Context, email string, mailB
 	}
 	r.setBasicAuth(basicAuthUser, m.APIKey())
 
-	var res v4EmailValidationResp
+	var res EmailVerification
 	err := getResponseFromJSON(ctx, r, &res)
 	if err != nil {
 		return EmailVerification{}, err
 	}
-	return EmailVerification{
-		IsValid:             res.IsValid,
-		MailboxVerification: res.MailboxVerification,
-		Parts:               res.Parts,
-		Address:             res.Address,
-		DidYouMean:          res.DidYouMean,
-		IsDisposableAddress: res.IsDisposableAddress,
-		IsRoleAddress:       res.IsRoleAddress,
-		Reasons:             res.Reason,
-		Result:              res.Result,
-		Risk:                res.Risk,
-		Engagement:          res.Engagement,
-	}, nil
+	return res, nil
 }
diff --git a/mock_validation.go b/mock_validation.go
index 1a034d5..29291a5 100644
--- a/mock_validation.go
+++ b/mock_validation.go
@@ -2,8 +2,6 @@ package mailgun
 
 import (
 	"net/http"
-	"net/mail"
-	"strings"
 
 	"github.com/go-chi/chi/v5"
 )
@@ -19,14 +17,8 @@ func (ms *mockServer) validateEmailV4(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	var results v4EmailValidationResp
-	parts, err := mail.ParseAddress(r.FormValue("address"))
-	if err == nil {
-		results.IsValid = true
-		results.Parts.Domain = strings.Split(parts.Address, "@")[1]
-		results.Parts.LocalPart = strings.Split(parts.Address, "@")[0]
-		results.Parts.DisplayName = parts.Name
-	}
+	var results EmailVerification
+	results.Address = r.FormValue("address")
 	results.Reason = []string{"no-reason"}
 	results.Risk = "unknown"
 	results.Result = "deliverable"


Test patch:
diff --git a/email_validation_test.go b/email_validation_test.go
index f6bd54d..2d9edca 100644
--- a/email_validation_test.go
+++ b/email_validation_test.go
@@ -2,7 +2,6 @@ package mailgun_test
 
 import (
 	"context"
-	"encoding/json"
 	"testing"
 
 	"github.com/mailgun/mailgun-go/v4"
@@ -19,49 +18,13 @@ func TestEmailValidationV4(t *testing.T) {
 	ev, err := v.ValidateEmail(ctx, "foo@mailgun.com", false)
 	require.NoError(t, err)
 
-	assert.True(t, ev.IsValid)
-	assert.Equal(t, "", ev.MailboxVerification)
 	assert.False(t, ev.IsDisposableAddress)
 	assert.False(t, ev.IsRoleAddress)
-	assert.Equal(t, "", ev.Parts.DisplayName)
-	assert.Equal(t, "foo", ev.Parts.LocalPart)
-	assert.Equal(t, "mailgun.com", ev.Parts.Domain)
-	assert.Equal(t, "", ev.Reason)
-	assert.True(t, len(ev.Reasons) != 0)
-	assert.Equal(t, "no-reason", ev.Reasons[0])
+	assert.True(t, len(ev.Reason) != 0)
+	assert.Equal(t, "no-reason", ev.Reason[0])
 	assert.Equal(t, "unknown", ev.Risk)
 	assert.Equal(t, "deliverable", ev.Result)
 	assert.Equal(t, "disengaged", ev.Engagement.Behavior)
 	assert.False(t, ev.Engagement.Engaging)
 	assert.False(t, ev.Engagement.IsBot)
 }
-
-func TestUnmarshallResponse(t *testing.T) {
-	payload := []byte(`{
-		"address": "some_email@aol.com",
-		"did_you_mean": null,
-		"is_disposable_address": false,
-		"is_role_address": false,
-		"is_valid": true,
-		"mailbox_verification": "unknown",
-		"parts":
-		{
-			"display_name": null,
-			"domain": "aol.com",
-			"local_part": "some_email"
-		},
-		"reason": "no-reason"
-	}`)
-	var ev mailgun.EmailVerification
-	err := json.Unmarshal(payload, &ev)
-	require.NoError(t, err)
-
-	assert.True(t, ev.IsValid)
-	assert.Equal(t, "unknown", ev.MailboxVerification)
-	assert.False(t, ev.IsDisposableAddress)
-	assert.False(t, ev.IsRoleAddress)
-	assert.Equal(t, "", ev.Parts.DisplayName)
-	assert.Equal(t, "some_email", ev.Parts.LocalPart)
-	assert.Equal(t, "aol.com", ev.Parts.Domain)
-	assert.Equal(t, "no-reason", ev.Reason)
-}
diff --git a/examples_test.go b/examples_test.go
index 8bdfd69..261a214 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -16,7 +16,7 @@ import (
 )
 
 func ExampleEmailValidatorImpl_ValidateEmail() {
-	v := mailgun.NewEmailValidator("my_private_api_key")
+	v := mailgun.NewEmailValidator("my_api_key")
 
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
 	defer cancel()
@@ -25,10 +25,6 @@ func ExampleEmailValidatorImpl_ValidateEmail() {
 	if err != nil {
 		log.Fatal(err)
 	}
-	if !ev.IsValid {
-		log.Fatal("Expected valid e-mail address")
-	}
-	log.Printf("Parts local_part=%s domain=%s display_name=%s", ev.Parts.LocalPart, ev.Parts.Domain, ev.Parts.DisplayName)
 	if ev.DidYouMean != "" {
 		log.Printf("The address is syntactically valid, but perhaps has a typo.")
 		log.Printf("Did you mean %s instead?", ev.DidYouMean)