JavaScript中的电子邮件验证:底层工作原理(代码解析)

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何在JavaScript中验证电子邮件:从简单正则表达式到深入底层解析

\n\n

每个开发者一生中至少都会遇到一个问题:“如何在JavaScript中验证电子邮件地址?”。这个问题在Stack Overflow上获得了数千次浏览和数百个回答,因为这个话题充满了细微差别。今天,我们不仅会提供现成的代码,还会深入底层:分析为什么简单的检查可能会漏掉a@b,或者阻止"test@[IPv6:2001:db8::1]"。开始吧!

\n\n

为什么“仅仅用正则表达式”是个坏主意?

\n\n

互联网上最流行的解决方案是复制一个正则表达式。但老实说:电子邮件地址就是一团乱麻。RFC 5321和RFC 5322规范允许使用+、-、.、%等字符,甚至允许括号内的注释。还有像museum或@[192.168.1.1]这样的域名。试着把所有这些东西塞进一行正则表达式——你要么会漏掉一个有效的地址,要么会阻止一个真实用户。

\n\n

下面是一个在Stack Overflow上常见的例子:

\n\n
const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
\n\n

这段代码在90%的情况下有效,但是:

\n
    \n
  • 会漏掉test@localhost(对本地网络有效)
  • \n
  • 会阻止"test@[192.168.1.1]"(根据RFC是有效的)
  • \n
  • 不检查域名长度或点号的存在
  • \n
\n\n

教训:不要试图编写完美的正则表达式。最好使用简单检查 + 服务器端验证的组合。

\n\n

电子邮件地址的解剖:编写代码前需要了解的知识

\n\n

在编写验证器之前,让我们根据规范来分析电子邮件的结构:

\n\n
    \n
  • 本地部分(@之前):可以包含字母、数字、点号、加号、连字符,但不能以点号开头或结尾。允许使用引号来表示特殊字符。
  • \n
  • 域名(@之后):由点号分隔的标签组成。每个标签长度为1到63个字符。域名可以是方括号内的IP地址。
  • \n
  • 总长度:不超过254个字符。
  • \n
\n\n

了解了这些,我们就可以编写更有意义的检查了。

\n\n

步骤1:简单但有效的验证(适用于99%的情况)

\n\n

我们从生产项目中使用的代码开始(例如,在Angular或React中)。它并不完美,但对于大多数表单来说已经足够了:

\n\n
function isEmailSimple(email) {\n    // 去除空格\n    const trimmed = email.trim();\n    \n    // 检查空字符串\n    if (!trimmed) return false;\n    \n    // 基本结构:某物 @ 某物 . 某物\n    const atIndex = trimmed.lastIndexOf('@');\n    if (atIndex < 1 || atIndex === trimmed.length - 1) return false;\n    \n    const localPart = trimmed.slice(0, atIndex);\n    const domain = trimmed.slice(atIndex + 1);\n    \n    // 域名必须至少包含一个点号\n    const dotIndex = domain.lastIndexOf('.');\n    if (dotIndex < 1 || dotIndex === domain.length - 1) return false;\n    \n    // 检查长度\n    if (trimmed.length > 254) return false;\n    if (localPart.length > 64) return false;\n    \n    return true;\n}\n\n// 示例:\nconsole.log(isEmailSimple('user@example.com')); // true\nconsole.log(isEmailSimple('a@b.c')); // true(形式上有效)\nconsole.log(isEmailSimple('user@localhost')); // false(没有点号)\nconsole.log(isEmailSimple('@example.com')); // false\n
\n\n

这段代码已经比盲目的正则表达式好多了。它检查了结构、长度以及@和点号的存在。但它会漏掉user@[192.168.1.1]——对于大多数网页表单来说,这并不关键。

\n\n

步骤2:考虑RFC的高级验证(几乎和浏览器一样)

\n\n

现代浏览器通过type="e属性使用内置验证。

博客

书籍推荐