package checkmail import ( "errors" "fmt" "net" "net/smtp" "regexp" "strings" "time" ) type SmtpError struct { Err error } func (e SmtpError) Error() string { return e.Err.Error() } func (e SmtpError) Code() string { return e.Err.Error()[0:3] } func NewSmtpError(err error) SmtpError { return SmtpError{ Err: err, } } const forceDisconnectAfter = time.Second * 10 var ( ErrBadFormat = errors.New("invalid format") ErrUnresolvableHost = errors.New("unresolvable host") //emailRegexp = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") emailRegexp = regexp.MustCompile("^.+?@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") ) func ValidateFormat(email string) error { if !emailRegexp.MatchString(email) { return ErrBadFormat } return nil } func ValidateHost(email string) error { _, host := split(email) mx, err := net.LookupMX(host) if err != nil { return ErrUnresolvableHost } client, err := smtp.Dial(fmt.Sprintf("%s:%d", mx[0].Host, 25)) if err != nil { return NewSmtpError(err) } defer client.Close() t := time.AfterFunc(forceDisconnectAfter, func() { client.Close() }) defer t.Stop() err = client.Hello("checkmail.me") if err != nil { return NewSmtpError(err) } err = client.Mail("lansome-cowboy@gmail.com") if err != nil { return NewSmtpError(err) } err = client.Rcpt(email) if err != nil { return NewSmtpError(err) } return nil } func split(email string) (account, host string) { i := strings.LastIndexByte(email, '@') account = email[:i] host = email[i+1:] return }