Skip to content

Commit

Permalink
CheckExchange and CheckHost (#68)
Browse files Browse the repository at this point in the history
Added to `StringValidEmail` and `NetIsHostname`
  • Loading branch information
marrow16 authored Nov 11, 2022
1 parent b1ed4ae commit 5f19a94
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 47 deletions.
68 changes: 24 additions & 44 deletions constraints_misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package valix
import (
"fmt"
"golang.org/x/text/language"
"net"
"net/mail"
"strconv"
"strings"
Expand Down Expand Up @@ -304,6 +305,8 @@ func (c *StringValidCurrencyCode) GetMessage(tcx I18nContext) string {
type StringValidEmail struct {
// DisallowRFC5322 when set, disallows email addresses in RFC5322 format (i.e "Barry Gibbs <bg@example.com>")
DisallowRFC5322 bool
// CheckExchange when set, checks the MX (mail exchange) for the email address
CheckExchange bool
// AllowIPAddress when set, allows email addresses with IP (e.g. "me@[123.0.1.2]")
AllowIPAddress bool
// AllowIPV6 when set, allows email addresses with IP v6 (e.g. "me@[2001:db8::68]")
Expand Down Expand Up @@ -354,54 +357,22 @@ func (c *StringValidEmail) Check(v interface{}, vcx *ValidatorContext) (bool, st
}

func (c *StringValidEmail) checkString(str string, vcx *ValidatorContext) bool {
result := false
if c.DisallowRFC5322 {
if isValidEmail(str, domainOptions{
allowIPAddress: c.AllowIPAddress,
allowIPV6: c.AllowIPV6,
allowLocal: c.AllowLocal,
allowTldOnly: c.AllowTldOnly,
allowGeographicTlds: c.AllowGeographicTlds,
allowGenericTlds: c.AllowGenericTlds,
allowBrandTlds: c.AllowBrandTlds,
allowInfraTlds: c.AllowInfraTlds,
allowTestTlds: c.AllowTestTlds,
addCountryCodeTlds: c.AddCountryCodeTlds,
excCountryCodeTlds: c.ExcCountryCodeTlds,
addGenericTlds: c.AddGenericTlds,
excGenericTlds: c.ExcGenericTlds,
addBrandTlds: c.AddBrandTlds,
excBrandTlds: c.ExcBrandTlds,
addLocalTlds: c.AddLocalTlds,
excLocalTlds: c.ExcLocalTlds,
}) {
return true
}
result = c.checkEmailAddress(str)
} else if a, err := mail.ParseAddress(str); err != nil {
// fails to parse addresses with IPv6 - so try directly...
if c.AllowIPAddress {
if isValidEmail(str, domainOptions{
allowIPAddress: c.AllowIPAddress,
allowIPV6: c.AllowIPV6,
allowLocal: c.AllowLocal,
allowTldOnly: c.AllowTldOnly,
allowGeographicTlds: c.AllowGeographicTlds,
allowGenericTlds: c.AllowGenericTlds,
allowBrandTlds: c.AllowBrandTlds,
allowInfraTlds: c.AllowInfraTlds,
allowTestTlds: c.AllowTestTlds,
addCountryCodeTlds: c.AddCountryCodeTlds,
excCountryCodeTlds: c.ExcCountryCodeTlds,
addGenericTlds: c.AddGenericTlds,
excGenericTlds: c.ExcGenericTlds,
addBrandTlds: c.AddBrandTlds,
excBrandTlds: c.ExcBrandTlds,
addLocalTlds: c.AddLocalTlds,
excLocalTlds: c.ExcLocalTlds,
}) {
return true
}
result = c.checkEmailAddress(str)
}
} else if isValidEmail(a.Address, domainOptions{
} else {
result = c.checkEmailAddress(a.Address)
}
return result
}

func (c *StringValidEmail) checkEmailAddress(addr string) bool {
if isValidEmail(addr, domainOptions{
allowIPAddress: c.AllowIPAddress,
allowIPV6: c.AllowIPV6,
allowLocal: c.AllowLocal,
Expand All @@ -420,7 +391,16 @@ func (c *StringValidEmail) checkString(str string, vcx *ValidatorContext) bool {
addLocalTlds: c.AddLocalTlds,
excLocalTlds: c.ExcLocalTlds,
}) {
return true
if c.CheckExchange {
if aAt := strings.LastIndex(addr, "@"); aAt != -1 {
dom := addr[aAt+1:]
if mxs, err := net.LookupMX(dom); err == nil && len(mxs) > 0 {
return true
}
}
} else {
return true
}
}
return false
}
Expand Down
13 changes: 12 additions & 1 deletion constraints_misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,11 @@ func TestStringValidEmail(t *testing.T) {
},
},
"me@google.com": {
expectValid: true,
expectValid: true,
expectValidWithOptions: true,
tryWith: &StringValidEmail{
CheckExchange: true,
},
},
"me2@google.com": {
expectValid: true,
Expand Down Expand Up @@ -669,6 +673,13 @@ func TestStringValidEmail(t *testing.T) {
AllowInfraTlds: true,
},
},
"me@xxx-yyy-zzz.com": {
expectValid: true,
expectValidWithOptions: false,
tryWith: &StringValidEmail{
CheckExchange: true,
},
},
}
for addr, tc := range testCases {
t.Run(fmt.Sprintf("Email:\"%s\"", addr), func(t *testing.T) {
Expand Down
15 changes: 13 additions & 2 deletions constraints_net.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func (c *NetIsCIDR) GetMessage(tcx I18nContext) string {

// NetIsHostname constraint to check that string value is a valid hostname
type NetIsHostname struct {
// CheckHost when set, checks the host (using net.LookupHost)
CheckHost bool
// AllowIPAddress when set, allows IP address hostnames
AllowIPAddress bool
// AllowIPV6 when set, allows IP v6 address hostnames
Expand Down Expand Up @@ -128,7 +130,7 @@ func (c *NetIsHostname) Check(v interface{}, vcx *ValidatorContext) (bool, strin
}

func (c *NetIsHostname) checkString(str string, vcx *ValidatorContext) bool {
return len(str) > 0 && isValidDomain(str, domainOptions{
if len(str) > 0 && isValidDomain(str, domainOptions{
allowIPAddress: c.AllowIPAddress,
allowIPV6: c.AllowIPV6,
allowLocal: c.AllowLocal,
Expand All @@ -146,7 +148,16 @@ func (c *NetIsHostname) checkString(str string, vcx *ValidatorContext) bool {
excBrandTlds: c.ExcBrandTlds,
addLocalTlds: c.AddLocalTlds,
excLocalTlds: c.ExcLocalTlds,
})
}) {
if c.CheckHost {
if addrs, err := net.LookupHost(str); err == nil && len(addrs) > 0 {
return true
}
} else {
return true
}
}
return false
}

// GetMessage implements the Constraint.GetMessage
Expand Down
18 changes: 18 additions & 0 deletions constraints_net_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,24 @@ func TestNetIsHostname(t *testing.T) {
ExcBrandTlds: []string{"audi"},
}, false},
},
"goxxx.compare": {
{&NetIsHostname{
AllowGenericTlds: true,
}, true},
{&NetIsHostname{
CheckHost: true,
AllowGenericTlds: true,
}, false},
},
"go.compare": {
{&NetIsHostname{
AllowGenericTlds: true,
}, true},
{&NetIsHostname{
CheckHost: true,
AllowGenericTlds: true,
}, true},
},
}
for a, tcs := range testCases {
for i, tc := range tcs {
Expand Down

0 comments on commit 5f19a94

Please sign in to comment.