如何在 Go 中验证电子邮件地址
Posted
技术标签:
【中文标题】如何在 Go 中验证电子邮件地址【英文标题】:How to validate an email address in Go 【发布时间】:2021-06-11 21:27:44 【问题描述】:我检查了 *** 并找不到任何可以回答如何在 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)?
【问题讨论】:
github.com/goware/emailx github.com/badoux/checkmail 1.该语言称为 Go。 2. 无论哪种语言,正则表达式和电子邮件地址都不能很好地混合。 【参考方案1】:标准库内置了电子邮件解析和验证,只需使用: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
【讨论】:
感谢您,它在大多数情况下都有效。不过,我对以下无效电子邮件仍有一些问题:“email@example.com (Joe Smith)”、“email@example” 得到了它,就像在 RFC 5322 的文档中一样,它写的是它正在检查域。这是screenshot,那么为什么“email@example”地址会失败。 @RiyazKhanexample
是一个有效的域,就像example.com
。它不一定要指定公共域,它可以是本地网络的本地域。至于(Joe Smith)
部分:这是一条评论,可能在电子邮件中的任何位置,请参阅Wikipedia: Email address。相信我,net/mail
包可以比您的自定义解决方案更好、更快、更可靠地解析电子邮件地址。
我认为这不是一封有效的电子邮件“bad-example@t”
@tile 根据RFC 5322 是有效的。 t
可能是有效的本地域名。在上面的cmets中提到,域可以是本地域,不一定是公共域。【参考方案2】:
@icza 的上述方法很好,但是,如果我们在登录/注册表单验证中使用它,很多人会输入部分或不正确的电子邮件地址,这将在生产中创建一堆无效记录。此外,谁知道我们可能会因此而被杀?。
因此,我使用正则表达式解决方案来验证标准电子邮件:
代码如下:
func isEmailValid(e string) bool
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]2,4$`)
return emailRegex.MatchString(e)
测试用例:
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
【讨论】:
即使是 SO 最烂的答案也承认 $ 被接受。 ***.com/a/2049510/4466350play.golang.org/p/iI2GeEmHRzE 相信我,mail.ParseAddress()
做得比你能做的更好。它接受本地域,但告诉我,你确定this-surely-doesnt-exist-just-showing-this-will-pass@nowhereland.cum
是比good@mydomain
更好的“有效”电子邮件吗?无论如何,您都应该实施并要求进行电子邮件验证。否则,简单地验证电子邮件地址的语法是否正确几乎没有任何价值。
@icza 为什么mail.ParseAddress()
正在传递您的错误示例电子邮件this-surely-doesnt-exist-just-showing-this-will-pass@nowhereland.cum
?。谁在乎生产中的本地域,您可以在任何电子邮件提供商服务中注册一个像本地域一样的电子邮件地址吗?
@RiyazKhan 是的,您不能在gmail.com
使用本地域,因为gmail.com
是公共域。但是,如果一家公司为其员工提供电子邮件服务,是的,您可以使用(或者您可以仅使用)那里的本地域。
这会遗漏在域名部分和 TLD 中有效的非 ASCII 字符。此外,还有长度大于 4 的 ASCII TLD (en.wikipedia.org/wiki/List_of_Internet_top-level_domains)。而且,即使您有一个有效的电子邮件,您仍然需要检查它是否实际归您的用户所有。所以你必须要求电子邮件验证。【参考方案3】:
方法实现示例:
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 以包含注册所需的所有数据,例如电子邮件、用户、密码等。
【讨论】:
以上是关于如何在 Go 中验证电子邮件地址的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 smtplib 在 Python 中验证电子邮件地址