github.com/go-email-validator/go-email-validator@v0.0.0-20230409163946-b8b9e6a0552e/pkg/presentation/as-email-verifier/dep.go (about)

     1  package asemailverifier
     2  
     3  import (
     4  	"github.com/go-email-validator/go-email-validator/pkg/ev"
     5  	"github.com/go-email-validator/go-email-validator/pkg/ev/evmail"
     6  	"github.com/go-email-validator/go-email-validator/pkg/presentation/converter"
     7  	"regexp"
     8  )
     9  
    10  const (
    11  	// Name of https://github.com/AfterShip/email-verifier converter
    12  	Name converter.Name = "AfterShipEmailVerifier"
    13  
    14  	// EmailRegexString is an email regex
    15  	EmailRegexString = "^(?:(?:(?:(?:[a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(?:\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|(?:(?:\\x22)(?:(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(?:\\x20|\\x09)+)?(?:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(?:(?:(?:\\x20|\\x09)*(?:\\x0d\\x0a))?(\\x20|\\x09)+)?(?:\\x22))))@(?:(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(?:(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])(?:[a-zA-Z]|\\d|-|\\.|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*(?:[a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
    16  )
    17  
    18  // DepPresentation is a presentation
    19  type DepPresentation struct {
    20  	Email        string                `json:"email"`
    21  	Reachable    Reachable             `json:"reachable"`
    22  	Syntax       *SyntaxPresentation   `json:"syntax"`
    23  	SMTP         *SMTPPresentation     `json:"smtp"`
    24  	Gravatar     *GravatarPresentation `json:"gravatar"`
    25  	Suggestion   string                `json:"suggestion"`
    26  	Disposable   bool                  `json:"disposable"`
    27  	RoleAccount  bool                  `json:"role_account"`
    28  	Free         bool                  `json:"free"`
    29  	HasMxRecords bool                  `json:"has_mx_records"`
    30  }
    31  
    32  // DepConverter converts ev.ValidationResult in DepPresentation
    33  type DepConverter struct {
    34  	converter          converter.CompositeConverter
    35  	calculateReachable FuncReachable
    36  }
    37  
    38  // NewDepConverterDefault creates default DepConverter
    39  func NewDepConverterDefault() DepConverter {
    40  	return NewDepConverter(
    41  		converter.NewCompositeConverter(converter.MapConverters{
    42  			ev.SMTPValidatorName:     converter.NewSMTPConverter(),
    43  			ev.SyntaxValidatorName:   SyntaxConverter{},
    44  			ev.GravatarValidatorName: GravatarConverter{},
    45  		}),
    46  		CalculateReachable,
    47  	)
    48  }
    49  
    50  // NewDepConverter creates DepConverter
    51  func NewDepConverter(converter converter.CompositeConverter, calculateReachable FuncReachable) DepConverter {
    52  	return DepConverter{converter, calculateReachable}
    53  }
    54  
    55  // Can ev.ValidationResult be converted in DepConverter
    56  func (DepConverter) Can(_ evmail.Address, result ev.ValidationResult, _ converter.Options) bool {
    57  	return result.ValidatorName() == ev.DepValidatorName
    58  }
    59  
    60  // Convert ev.ValidationResult in DepConverter
    61  func (s DepConverter) Convert(email evmail.Address, resultInterface ev.ValidationResult, opts converter.Options) interface{} {
    62  	depResult := resultInterface.(ev.DepValidationResult)
    63  	validationResults := depResult.GetResults()
    64  
    65  	var syntax *SyntaxPresentation
    66  	var smtp *SMTPPresentation
    67  	var gravatar *GravatarPresentation
    68  	mxResult := validationResults[ev.MXValidatorName].(ev.MXValidationResult)
    69  	for _, validatorResult := range depResult.GetResults() {
    70  		if !s.converter.Can(email, validatorResult, opts) {
    71  			continue
    72  		}
    73  
    74  		switch v := s.converter.Convert(email, validatorResult, opts).(type) {
    75  		case *SyntaxPresentation:
    76  			syntax = v
    77  		case converter.SMTPPresentation:
    78  			smtp = &SMTPPresentation{
    79  				HostExists:  v.CanConnectSMTP,
    80  				FullInbox:   v.HasFullInbox,
    81  				CatchAll:    v.IsCatchAll,
    82  				Deliverable: !v.IsCatchAll && v.IsDeliverable,
    83  				Disabled:    v.IsDisabled,
    84  			}
    85  		case *GravatarPresentation:
    86  			gravatar = v
    87  		}
    88  	}
    89  
    90  	depPresentation := DepPresentation{
    91  		Email:     email.String(),
    92  		Reachable: ReachableUnknown,
    93  		Syntax:    syntax,
    94  	}
    95  
    96  	if syntax == nil || !syntax.Valid {
    97  		return depPresentation
    98  	}
    99  
   100  	depPresentation.Free = !validationResults[ev.FreeValidatorName].IsValid()
   101  	depPresentation.RoleAccount = !validationResults[ev.RoleValidatorName].IsValid()
   102  	depPresentation.Disposable = !validationResults[ev.DisposableValidatorName].IsValid()
   103  
   104  	if depPresentation.Disposable {
   105  		return depPresentation
   106  	}
   107  
   108  	if !mxResult.IsValid() {
   109  		return depPresentation
   110  	}
   111  
   112  	depPresentation.HasMxRecords = len(mxResult.MX()) > 0
   113  
   114  	if smtp == nil || !smtp.HostExists {
   115  		return depPresentation
   116  	}
   117  
   118  	depPresentation.SMTP = smtp
   119  	depPresentation.Reachable = s.calculateReachable(depPresentation)
   120  
   121  	if gravatar != nil {
   122  		depPresentation.Gravatar = gravatar
   123  	}
   124  
   125  	return depPresentation
   126  }
   127  
   128  // NewDepValidator is a default validator
   129  func NewDepValidator(smtpValidator ev.Validator) ev.Validator {
   130  	builder := ev.NewDepBuilder(nil)
   131  	if smtpValidator == nil {
   132  		smtpValidator = builder.Get(ev.SMTPValidatorName)
   133  	}
   134  
   135  	return ev.NewDepBuilder(nil).Set(
   136  		ev.SyntaxValidatorName,
   137  		ev.NewSyntaxRegexValidator(regexp.MustCompile(EmailRegexString)),
   138  	).
   139  		Set(ev.GravatarValidatorName, ev.NewGravatarValidator()).
   140  		Set(ev.SMTPValidatorName, smtpValidator).
   141  		Set(ev.FreeValidatorName, ev.FreeDefaultValidator()).
   142  		Build()
   143  }