85 lines
1.7 KiB
Go
85 lines
1.7 KiB
Go
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
|
|
}
|