diff --git a/models/user.go b/models/user.go index 701bc1f..43e2bb3 100644 --- a/models/user.go +++ b/models/user.go @@ -4,6 +4,7 @@ import ( "crypto/md5" "fmt" conf "github.com/muety/wakapi/config" + "github.com/muety/wakapi/utils" "regexp" "strings" "time" @@ -190,8 +191,9 @@ func ValidatePassword(password string) bool { return len(password) >= 6 } +// ValidateEmail checks that, if an email address is given, it has proper syntax and (if not in dev mode) an MX record exists for the domain func ValidateEmail(email string) bool { - return email == "" || mailRegex.Match([]byte(email)) + return email == "" || (mailRegex.Match([]byte(email)) && (conf.Get().IsDev() || utils.CheckEmailMX(email))) } func ValidateTimezone(tz string) bool { diff --git a/routes/settings.go b/routes/settings.go index 81d5294..d1a0448 100644 --- a/routes/settings.go +++ b/routes/settings.go @@ -178,7 +178,7 @@ func (h *SettingsHandler) actionUpdateUser(w http.ResponseWriter, r *http.Reques } if !payload.IsValid() { - return http.StatusBadRequest, "", "invalid parameters" + return http.StatusBadRequest, "", "invalid parameters - perhaps invalid e-mail address?" } if payload.Email == "" && user.HasActiveSubscription() { diff --git a/scripts/email_checker.go b/scripts/email_checker.go new file mode 100644 index 0000000..7b48d99 --- /dev/null +++ b/scripts/email_checker.go @@ -0,0 +1,55 @@ +package main + +// Usage example: +// cat emails.txt go run email_checker.go > result.txt + +import ( + "bufio" + "fmt" + "log" + "net" + "os" + "regexp" + "strings" +) + +const MailPattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+" + +var mailRegex *regexp.Regexp + +func init() { + mailRegex = regexp.MustCompile(MailPattern) +} + +func CheckEmailMX(email string) bool { + parts := strings.Split(email, "@") + if len(parts) != 2 { + return false + } + records, err := net.LookupMX(parts[1]) + return len(records) > 0 && err == nil +} + +func ValidateEmail(email string) bool { + return mailRegex.Match([]byte(email)) && CheckEmailMX(email) +} + +func main() { + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + email := scanner.Text() + if email == "" { + return + } + + if ValidateEmail(email) { + fmt.Printf("[+] %s\n", email) + } else { + fmt.Printf("[-] %s\n", email) + } + } + + if err := scanner.Err(); err != nil { + log.Fatal(err) + } +} diff --git a/utils/dns.go b/utils/dns.go new file mode 100644 index 0000000..5c76159 --- /dev/null +++ b/utils/dns.go @@ -0,0 +1,16 @@ +package utils + +import ( + "net" + "strings" +) + +// CheckEmailMX takes an e-mail address and verifies that an MX DNS record exists for its domain +func CheckEmailMX(email string) bool { + parts := strings.Split(email, "@") + if len(parts) != 2 { + return false + } + records, err := net.LookupMX(parts[1]) + return len(records) > 0 && err == nil +}