func lookupHost(domain string) (string, error) {
	if mx, err := net.LookupMX(domain); err == nil {
		return mx[0].Host, nil
	}
	if ips, err := net.LookupIP(domain); err == nil {
		return ips[0].String(), nil  
	}
	return "", fmt.Errorf("failed finding MX and A records for domain %s", domain)
}
lookupHost first checks if any MX records are available and if not, it will check
if A records are available as they can resolve email server hosts. An error indicates
that non of the A or MX records are available.
package emailaddress
import (
	"fmt"
	"net"
	"net/smtp"
	"regexp"
	"strings"
	"golang.org/x/net/publicsuffix"
)
var (
	rfc5322          = "(?i)(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"
	validEmailRegexp = regexp.MustCompile(fmt.Sprintf("^%s*$", rfc5322))
	findEmailRegexp  = regexp.MustCompile(rfc5322)
)
type EmailAddress struct {
	LocalPart string
	Domain string
}
func (e EmailAddress) String() string {
	if e.LocalPart == "" || e.Domain == "" {
		return ""
	}
	return fmt.Sprintf("%s@%s", e.LocalPart, e.Domain)
}
func (e EmailAddress) ValidateHost() error {
	host, err := lookupHost(e.Domain)
	if err != nil {
		return err
	}
	return tryHost(host, e)
}
func (e EmailAddress) ValidateIcanSuffix() error {
	d := strings.ToLower(e.Domain)
	if s, icann := publicsuffix.PublicSuffix(d); !icann {
		return fmt.Errorf("public suffix is not managed by ICANN, got %s", s)
	}
	return nil
}
func Find(haystack []byte, validateHost bool) (emails []*EmailAddress) {
	results := findEmailRegexp.FindAll(haystack, -1)
	for _, r := range results {
		if e, err := Parse(string(r)); err == nil {
			if validateHost {
				if err := e.ValidateHost(); err != nil {
					continue
				}
			}
			emails = append(emails, e)
		}
	}
	return emails
}
func FindWithIcannSuffix(haystack []byte, validateHost bool) (emails []*EmailAddress) {
	results := Find(haystack, false)
	for _, e := range results {
		if err := e.ValidateIcanSuffix(); err == nil {
			if validateHost {
				if err := e.ValidateHost(); err != nil {
					continue
				}
			}
			emails = append(emails, e)
		}
	}
	return emails
}
func Parse(email string) (*EmailAddress, error) {
	if !validEmailRegexp.MatchString(email) {
		return nil, fmt.Errorf("format is incorrect for %s", email)
	}
	i := strings.LastIndexByte(email, '@')
	e := &EmailAddress{
		LocalPart: email[:i],
		Domain:    email[i+1:],
	}
	return e, nil
}