为什么HTML5表单验证允许没有点的电子邮件?

162

我正在撰写一个非常简单的模型来演示一些HTML5表单验证。然而,我注意到电子邮件验证没有检查地址中是否有点,也没有检查点后面的字符。

换句话说,“john@doe”被认为是有效的,但它显然不是一个有效的电子邮件地址;“doe”不是一个域名。

这是我如何编写我的电子邮件字段:

<input type="email" required />

这不够吗?

查看这个示例,你就明白我想说什么了。

注意: 我知道可以使用正则表达式模式来完成此操作。我只是想知道有人如何能够使用电子邮件类型而不出问题。


2
@Katana314 - 嘿,是的。大多数(配置良好的)邮件服务器将拒绝发送到不匹配预期域的地址的消息,因此一般来说使用localhost地址没有问题。 - admdrew
9个回答

178
你理论上可以有一个没有“.”的地址。
由于技术上这样的事情:
user@com
user@localserver
user@[IPv6:2001:db8::1]

所有有效的电子邮件。
因此,标准的HTML5验证允许包括不常见的所有有效电子邮件。
为了更容易理解(而不是阅读标准)的解释,请参考以下链接: http://en.wikipedia.org/wiki/Email_address#Examples

3
同意,这个回答了“为什么”,而不是“解决方案”。我也很好奇为什么。现在我知道不要“修复”了。 - Eleanor Zimmermann
1
第一种类型的例子是域名uz,截至2018年10月,它直接指向一个IP地址。如果你执行nslookup uz,它会指向91.212.89.8,因此在这个域名上也应该可以使用电子邮件。 - pulsejet
2
无点域名也被允许在电子邮件中使用。请阅读本文,其中解释了这种无点域名的情况:https://www.bleepingcomputer.com/news/technology/dotless-domains-home-to-the-internet-s-shortest-urls/ - Arkowsky

115
因为a@b是一个有效的电子邮件地址(例如localhost是一个有效的域名)。请参见http://en.wikipedia.org/wiki/Email_address#Examples 此外,请记住您应该始终在服务器端进行输入验证。客户端验证仅用于向用户提供反馈,不能依赖于它,因为它可以轻易地被绕过。

13
谢谢。我只是不明白任何公司如何从这种开箱即用的电子邮件验证中受益。Facebook 不会允许有人使用 a@b 地址注册。不过还是谢谢提供信息。(我没有对你的回答投反对票) - WEFX
11
对于像Facebook这样公开访问的网站,这种方式是无用的。但是考虑一下内部网站。您可能想给joe@support写信。但我认为这种方式的用处很小。尽管如此,网络浏览器应基于标准(即RFC),而不是基于最常见的情况实现。 - Ali Alavi
14
我想知道有多久没有人实际发送电子邮件到本地主机了! - Matthew Lock
4
作为附注,目前最短的工作电子邮件地址之一(https://recordsetter.com/world-record/shortest-email-address/4327)是 au@ua - Kyborek
2
根据RFC822,“a@b”是一个有效的地址,但这并不是故事的结束。ICANN在2013年禁止了所谓的“无点”域名,因此它们是否在语法上有效已经不再相关。 - Synchro
显示剩余5条评论

34

尝试将此内容添加到输入框中

pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,63}$"

Fiddle


63
首先,你甚至没试着解释这个规则允许或限制什么,以及为什么有人会需要这些规则。其次,它比标准所允许的要严格得多(我不会假装已经阅读并理解这些标准,但是请参考例如http://en.wikipedia.org/wiki/Email_address#Internationalization或在Stack Overflow上的许多电子邮件验证问题中关于奇怪电子邮件地址的例子)。为什么要这样做?如果有人输入了不寻常的电子邮件地址,就接受它吧 - 可能他们比你更懂。 - Mark Amery
9
我认为,“chances are”他们在犯错误。也许他们有一个非常不寻常的电子邮件地址,但我想大多数情况下,如果您停止通过验证并提示用户检查,您只会得到一个正确的电子邮件地址替代错误的地址。 - Geoff Kendall
3
这段代码应该有一个 ^,表示它应该从字符串的开头开始匹配,并接受大写字母:^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+$ - Kohjah Breese

17

这个 MDN 页面展示了浏览器应该使用的正则表达式来验证电子邮件地址:

https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/email#Validation

您可以稍微更改此正则表达式,以要求域名中至少有一个点:将正则表达式末尾的星号 * 改为加号 +。然后将该正则表达式用作 pattern 属性:

<form>
  <input
    type="email"
    pattern="^[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])?)+$"
    title="Valid e-mail address including top-level domain"
    required
  />
  <button type="submit">Test</button>
</form>


1
这不是完全合格的验证。例如,".test@test.com"和"test.@test.com"根据RFC无效。 - Ole K

15

RFC 822第6章规定了一种使用增强的Backus-Naur形式(BNF)的地址格式:

addr-spec   =  local-part "@" domain
local-part  =  word *("." word)
domain      =  sub-domain *("." sub-domain)

使用该规范,a@b 是一个合法的地址。 更新 为了回答 Trejkaz 的评论,我添加了以下定义。我们可以看到空格是被允许的,但只能在引号内。
word          =  atom / quoted-string
atom          =  1*<any CHAR except specials, SPACE and CTLs>
quoted-string = <"> *(qtext/quoted-pair) <">
SPACE         =  <ASCII SP, space>
CTL           =  <any ASCII control character and DEL> 
qtext         =  <any CHAR excepting <">, "\" & CR, and including linear-white-space>
quoted-pair   =  "\" CHAR  

1
另一方面,RFC 822也允许我在本地部分中放置空格,但至少Chrome似乎不允许这样做,因此我不确定他们是否将RFC作为参考。(尽管他们应该这样做!) - Hakanai

3
您可以自定义电子邮件字段的格式:

input:valid {
  border-color: green
}

input:invalid {
  border-color: red
}
Email:
<input type="email" required value="a@b.c" /><br>

Non-dots Email:
<input type="email" required pattern="[^.]+@[^.]+" value="a@b.c" />


3

以下是使用HTML5和正则表达式模式进行操作的方法。您还可以添加自定义消息以显示。

<form>
  <input type="email" value="paul@test" required pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,63}$" title="Hey, you are missing domain part in the email !!!"/>
  <button type="submit">Click Me</button>
</form>


2

缺少顶级域名的主机名似乎是有效的。

我说“似乎”是因为这里有一个2013年ICANN禁止无点域名……

在2013年8月13日的会议上,ICANN董事会新通用顶级域名计划委员会(NGPC)通过了一项决议,确认“无点域名”是被禁止的。

但是从实际经验来看,它似乎从未得到执行。

无论如何,PHP函数FILTER_VALIDATE_EMAIL不允许使用无点域名。

因此,这里提供了一个简单的后端验证设置,包括您的电子邮件和必填字段:

if (empty($required_field) OR empty($another_required_field) OR
    !filter_var($email_field, FILTER_VALIDATE_EMAIL)) {
    // error handling here
    exit;
    }

虽然“格式错误”的电子邮件可能会通过浏览器,但它不会通过服务器。


参考资料:


-4

这个模式对我一直有效。

文本必须小写pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$",但我认为它涵盖了大多数电子邮件地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接