如何在 Go 中验证电子邮件地址
How to validate an email address in Go
我查看了 Whosebug,但找不到任何问题可以回答 如何使用 Go 语言验证电子邮件。
经过一番研究,我想通了,按我的需要解决了。
我有这个 regex 和 Go 函数,工作正常:
import (
"fmt"
"regexp"
)
func main() {
fmt.Println(isEmailValid("test44@gmail.com")) // true
fmt.Println(isEmailValid("test$@gmail.com")) // true -- expected "false"
}
// isEmailValid checks if the email provided is valid by regex.
func isEmailValid(e string) bool {
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])?)*$")
return emailRegex.MatchString(e)
}
问题是它接受我不想要的特殊字符。我尝试使用其他语言的“正则表达式”表达式,但它在调试中抛出错误 "unknown escape"。
谁能给我一个好的正则表达式或任何适用于 GoLang 的快速解决方案 (pkg)?
标准库内置了电子邮件解析和验证,只需使用:mail.ParseAddress()
.
一个简单的“有效”测试:
func valid(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}
正在测试:
for _, email := range []string{
"good@exmaple.com",
"bad-example",
} {
fmt.Printf("%18s valid: %t\n", email, valid(email))
}
哪些输出(在 Go Playground 上尝试):
good@exmaple.com valid: true
bad-example valid: false
The above approach from @icza is nice, however, if we use it in login/signup form validation, many people will enter a partial or incorrect email address, which will create a bunch of invalid records in production. Furthermore, who knows we might get killed because of that.
Therefore, I went to the regex solution to validate standard emails:
Here is the code:
func isEmailValid(e string) bool {
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`)
return emailRegex.MatchString(e)
}
Test Cases:
fmt.Println(isEmailValid("test44@gmail.com")) // true
fmt.Println(isEmailValid("bad-email")) // false
fmt.Println(isEmailValid("test44$@gmail.com")) // false
fmt.Println(isEmailValid("test-email.com")) // false
fmt.Println(isEmailValid("test+email@test.com")) // true
方法实现示例:
var 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])?)*$")
这与我创建结构的包在同一个包中
type EmailInputRegistration struct {
Email string
}
然后处理错误:
func (in EmailInputRegistration) Validate() error {
if !emailRegexp.MatchString(in.Email) {
return fmt.Errorf("%w: email invalid", ErrValidation)
}
//any other exception handling...
return nil
}
理想情况下,应重构此 EmailInputRegistration 以包含注册所需的所有数据,例如电子邮件、用户、密码等。
由于我发现正则表达式难以阅读,所以我更喜欢可读的无聊代码。例如:
// Accepts at least the x@y.zz pattern.
func isEmailAddress(v string) bool {
if v == "" {
return false
}
if containsWhitespace(v) {
return false
}
iAt := strings.IndexByte(v, '@')
if iAt == -1 {
return false
}
localPart := v[:iAt]
if localPart == "" {
return false
}
domain := v[iAt+1:]
if domain == "" {
return false
}
iDot := strings.IndexByte(domain, '.')
if iDot == -1 || iDot == 0 || iDot == len(domain)-1 {
return false
}
if strings.Index(domain, "..") != -1 {
return false
}
iTLD := strings.LastIndexByte(domain, '.')
return 2 <= len([]rune(domain[iTLD+1:]))
}
func containsWhitespace(v string) bool {
for _, r := range v {
if unicode.IsSpace(r) {
return true
}
}
return false
}
我查看了 Whosebug,但找不到任何问题可以回答 如何使用 Go 语言验证电子邮件。
经过一番研究,我想通了,按我的需要解决了。
我有这个 regex 和 Go 函数,工作正常:
import (
"fmt"
"regexp"
)
func main() {
fmt.Println(isEmailValid("test44@gmail.com")) // true
fmt.Println(isEmailValid("test$@gmail.com")) // true -- expected "false"
}
// isEmailValid checks if the email provided is valid by regex.
func isEmailValid(e string) bool {
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])?)*$")
return emailRegex.MatchString(e)
}
问题是它接受我不想要的特殊字符。我尝试使用其他语言的“正则表达式”表达式,但它在调试中抛出错误 "unknown escape"。
谁能给我一个好的正则表达式或任何适用于 GoLang 的快速解决方案 (pkg)?
标准库内置了电子邮件解析和验证,只需使用:mail.ParseAddress()
.
一个简单的“有效”测试:
func valid(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}
正在测试:
for _, email := range []string{
"good@exmaple.com",
"bad-example",
} {
fmt.Printf("%18s valid: %t\n", email, valid(email))
}
哪些输出(在 Go Playground 上尝试):
good@exmaple.com valid: true
bad-example valid: false
The above approach from @icza is nice, however, if we use it in login/signup form validation, many people will enter a partial or incorrect email address, which will create a bunch of invalid records in production. Furthermore, who knows we might get killed because of that.
Therefore, I went to the regex solution to validate standard emails:
Here is the code:
func isEmailValid(e string) bool {
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`)
return emailRegex.MatchString(e)
}
Test Cases:
fmt.Println(isEmailValid("test44@gmail.com")) // true
fmt.Println(isEmailValid("bad-email")) // false
fmt.Println(isEmailValid("test44$@gmail.com")) // false
fmt.Println(isEmailValid("test-email.com")) // false
fmt.Println(isEmailValid("test+email@test.com")) // true
方法实现示例:
var 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])?)*$")
这与我创建结构的包在同一个包中
type EmailInputRegistration struct {
Email string
}
然后处理错误:
func (in EmailInputRegistration) Validate() error {
if !emailRegexp.MatchString(in.Email) {
return fmt.Errorf("%w: email invalid", ErrValidation)
}
//any other exception handling...
return nil
}
理想情况下,应重构此 EmailInputRegistration 以包含注册所需的所有数据,例如电子邮件、用户、密码等。
由于我发现正则表达式难以阅读,所以我更喜欢可读的无聊代码。例如:
// Accepts at least the x@y.zz pattern.
func isEmailAddress(v string) bool {
if v == "" {
return false
}
if containsWhitespace(v) {
return false
}
iAt := strings.IndexByte(v, '@')
if iAt == -1 {
return false
}
localPart := v[:iAt]
if localPart == "" {
return false
}
domain := v[iAt+1:]
if domain == "" {
return false
}
iDot := strings.IndexByte(domain, '.')
if iDot == -1 || iDot == 0 || iDot == len(domain)-1 {
return false
}
if strings.Index(domain, "..") != -1 {
return false
}
iTLD := strings.LastIndexByte(domain, '.')
return 2 <= len([]rune(domain[iTLD+1:]))
}
func containsWhitespace(v string) bool {
for _, r := range v {
if unicode.IsSpace(r) {
return true
}
}
return false
}