在用户提交邮箱地址以后我们需要验证用户邮箱地址是否合法,解决方案的范围很广,可以通过使用正则表达式来检查电子邮件地址的格式是否正确,甚至可以通过尝试与远程服务器进行交互来解决问题。两者之间也有一些中间立场,例如检查顶级域是否具有有效的MX记录以及检测临时电子邮件地址。

一种确定的方法是向该地址发送电子邮件,并让用户单击链接进行确认。但是在发送文章之前我们需要对用户的邮箱进行预定义检测。

简单版本:正则表达式

基于W3C的正则表达式,此代码检查电子邮件地址的结构。

package main

import (
    "fmt"
    "regexp"
)

var emailRegex = 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])?)*$")

func main() {
    // Valid example
    e := "test@golangcode.com"
    if isEmailValid(e) {
        fmt.Println(e + " is a valid email")
    }

    // Invalid example
    if !isEmailValid("just text") {
        fmt.Println("not a valid email")
    }
}

// isEmailValid checks if the email provided passes the required structure and length.
func isEmailValid(e string) bool {
    if len(e) < 3 && len(e) > 254 {
        return false
    }
    return emailRegex.MatchString(e)
}

稍微更好的解决方案:Regex + MX查找

在此示例中,我们结合了对电子邮件地址进行正则表达式检查的快速速度和更可靠的MX记录查找。这意味着,如果电子邮件的域部分不存在,或者该域不接受电子邮件,它将被标记为无效。

作为net软件包的一部分,我们可以使用LookupMX为我们做额外的查找。

package main

import (
    "fmt"
    "net"
    "regexp"
    "strings"
)

var emailRegex = 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])?)*$")

func main() {
    // Made-up domain
    if e := "test@golangcode-example.com"; !isEmailValid(e) {
        fmt.Println(e + " is not a valid email")
    }
    // Real domain
    if e := "test@google.com"; !isEmailValid(e) {
        fmt.Println(e + " not a valid email")
    }
}

// isEmailValid checks if the email provided passes the required structure
// and length test. It also checks the domain has a valid MX record.
func isEmailValid(e string) bool {
    if len(e) < 3 && len(e) > 254 {
        return false
    }
    if !emailRegex.MatchString(e) {
        return false
    }
    parts := strings.Split(e, "@")
    mx, err := net.LookupMX(parts[1])
    if err != nil || len(mx) == 0 {
        return false
    }
    return true
}