Files
LambdaMail/services/protocols/internal/domain/valueobject/domain_name.go
T

50 lines
1.4 KiB
Go

package valueobject
import (
"errors"
"strings"
)
// DomainName is an RFC 1035 fully-qualified domain name, normalized to lowercase.
type DomainName struct {
value string
}
var (
ErrDomainNameEmpty = errors.New("domain name: must not be empty")
ErrDomainNameNotFQDN = errors.New("domain name: must contain at least one dot (not a FQDN)")
ErrDomainNameInvalidLabel = errors.New("domain name: label must not start or end with a hyphen")
)
// NewDomainName validates and normalizes raw into a DomainName.
func NewDomainName(raw string) (DomainName, error) {
if raw == "" {
return DomainName{}, ErrDomainNameEmpty
}
lower := strings.ToLower(raw)
labels := strings.Split(lower, ".")
if len(labels) < 2 {
return DomainName{}, ErrDomainNameNotFQDN
}
for _, label := range labels {
if label == "" || strings.HasPrefix(label, "-") || strings.HasSuffix(label, "-") {
return DomainName{}, ErrDomainNameInvalidLabel
}
}
return DomainName{value: lower}, nil
}
func (d DomainName) String() string { return d.value }
// IsPunycode reports whether the domain name is IDNA/punycode-encoded.
// It returns true if any label of the domain starts with the ASCII Compatible Encoding prefix "xn--".
func (d DomainName) IsPunycode() bool {
labels := strings.Split(d.value, ".")
for _, label := range labels {
if strings.HasPrefix(label, "xn--") {
return true
}
}
return false
}