使用正则表达式进行电子邮件地址验证






4.21/5 (48投票s)
本文讨论了使用正则表达式验证电子邮件地址的主题,并最终提供了一个 C# 工作示例项目。
引言
在几乎所有情况下,出于许多原因(例如安全性、可靠性、作为给定模板的证明等),验证用户输入都是一种好习惯。电子邮件验证是其中一个非常常见的用例。本文对此主题进行了简要讨论,并提供了一个非常简单的 C# static
类,该类可以作为“即用型”解决方案应用于给定的电子邮件验证任务。
背景
最近我一直在研究正则表达式,特别是用于电子邮件验证的正则表达式。我在网上找到的表达式似乎无法正确匹配我想要的所有电子邮件地址。例如,使用一个常见的电子邮件验证正则表达式,我成功匹配了以下电子邮件:“..@test.com”、“.a@test.com”、“.@s.dd”、“ab@988.120.150.10”、“ab@120.256.256.120”、“2@bde.cc”、“-@bde.cc”、“..@bde.cc”、“_@bde.cc”,这些显然不应被视为有效的电子邮件地址。
测试类和示例代码
验证类(见下文代码)和示例项目是用 C# 编写的。但这个东西非常简单,可以转换为任何支持正则表达式的编程语言。我试图让示例类尽可能简单,而且我认为它确实是最简单的。然而,验证表达式稍微复杂一些,需要进一步说明。
public static class TestEmail
{
/// <summary>
/// Regular expression, which is used to validate an E-Mail address.
/// </summary>
public const string MatchEmailPattern =
@"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@"
+ @"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?
[0-9]{1,2}|25[0-5]|2[0-4][0-9])\."
+ @"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?
[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
+ @"([a-zA-Z0-9]+[\w-]+\.)+[a-zA-Z]{1}[a-zA-Z0-9-]{1,23})$";
/// <summary>
/// Checks whether the given Email-Parameter is a valid E-Mail address.
/// </summary>
/// <param name="email">Parameter-string that contains an E-Mail address.</param>
/// <returns>True, when Parameter-string is not null and
/// contains a valid E-Mail address;
/// otherwise false.</returns>
public static bool IsEmail(string email)
{
if (email != null) return Regex.IsMatch(email, MatchEmailPattern);
else return false;
}
}
验证表达式
上面给出的电子邮件匹配表达式之所以看起来复杂,正是因为它确实如此。因此,在此处进行一些说明。在代码示例中,分配给 MatchEmailPattern
常量的匹配表达式由四部分组成。整个表达式以 ^
符号开头,以 $
符号结尾。这确保了匹配的是给定电子邮件字符串的所有字符,而不是其中的一部分。表达式的各个部分按如下方式匹配为一个整体表达式:
Expression = ExpressionPart1 AND (ExpressionPart2 OR
(ExpressionPart3 AND ExpressionPart4))
现在让我们描述匹配正则表达式的每个部分。
表达式部分 1
(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@
匹配电子邮件地址的用户名部分。此表达式部分匹配如下:
([\w-]+\.)+[\w-]+)
- 匹配点分隔的用户名组(例如,John.Connor@test.maildomain.com 中的 John.Connor)。
规则:应至少有两个点分隔的组,每个组应至少包含一个字母数字字符或“-
”、“_
”字符,并且末尾的点字符(最右侧到 @ 符号的组除外)。- 或
([a-zA-Z]{1}|[\w-]{2,})
- 匹配单个(无“.
”字符)用户名(例如,Max-Brown@test.maildomain.com 中的 Max-Brown)。
规则:如果用户名部分只有一个字符,则应为单词字符(a 到 z 或 A 到 Z),或者应至少包含两个字母数字、下划线或连字符字符。 @
- 匹配电子邮件地址的 @ 符号。
表达式部分 2
(([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.
([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}
匹配电子邮件地址的主机部分,如果主机在电子邮件地址中表示为 IP 地址。如您所见,此表达式部分有四个相同的重复组,每个组分别用于匹配 IP 地址的前三到四位八位字节。整个表达式部分匹配如下:
([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.
- 匹配电子邮件字符串中的 IP 地址的前三个八位字节之一(例如,John.Connor@195.250.101.219 中的 195.250.101.)。
规则:可选的第一个字符“0
”到“1
”,可选的第二个字符“0
”到“9
”,强制的第三个字符“0
”到“9
”或强制的第一个字符“25
”和强制的第三个字符“0
”到“5
”或强制的第一个字符“2
”和强制的第二个字符“0
”到“4
”和强制的第三个字符“0
”到“9
”以及八位字节组末尾的强制“.
”字符。([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])
- 匹配电子邮件字符串中 IP 地址的最后一个第四个八位字节(例如,John.Connor@195.250.101.219 中的 219)。
规则:与前三个八位字节的规则相同,只是末尾没有“.
”字符。{1}
- 匹配一个字符串,该字符串在 @ 符号之后仅包含一个“四八位字节”组。
表达式部分 3
([a-zA-Z0-9]+[\w-]+\.)+
匹配电子邮件主机名部分中的子域名(例如,John.Connor@test.maildomain.com 中的 test.maildomain 或 max@123reg.co.in 中的 123reg.co)。
规则:应至少有一个子域名。第一个字符是强制的,应为单词字符(a 到 z 或 A 到 Z)。第二个字符是强制的,应为字母数字字符、下划线或连字符字符。第三个及之后的所有字符都是可选的,应为字母数字字符、下划线或连字符字符。
表达式部分 4
[a-zA-Z]{1}[a-zA-Z0-9-]{1,23}
匹配电子邮件主机名部分中的顶级域(例如,John.Connor@test.maildomain.com 中的 com 或 INFO@MY.PHOTOGRAPHY 中的 PHOTOGRAPHY)。
规则:必须以一个单词字符(a 到 z、A 到 Z)开头,后面至少有一个到二十三个字母数字或“连字符”字符(a 到 z、A 到 Z、0 到 9 或 -)。当前的 TLD 列表(顶级域)可以在此处找到。如果您想匹配长度超过二十四个字符的顶级域(实际最大 TLD 字符数),可以将给定表达式中的“23
”字符更改为您想要的长度减一(例如,要匹配最多 100 个字符的顶级域,可以使用以下表达式:
[a-zA-Z]{1}[a-zA-Z0-9-]{1,99}
使用项目示例
要使用项目示例,您需要从上面的链接下载 EmailValidator.zip 文件,然后将其解压缩到计算机上的一个目录中。示例项目已在 Visual Studio 2005 中创建和测试,并在打包成 zip 文件之前进行了清理。因此,如果您使用 VS 2005,只需打开项目并进行生成即可。如果您使用 VS 2003,则可以创建一个新的控制台应用程序项目,删除自动创建的 Program.cs 文件,然后添加 EmailValidator.cs 和 TestEmail.cs 文件,然后生成项目。如果您使用 VS 2008,可以将 EmailValidator
项目转换为新格式,然后生成它。一旦示例项目生成完成,您就可以直接从 IDE 中启动 EmailValidator.exe 程序,或者使用 test.bat 文件。后一种情况甚至更有趣,因为那里有许多匹配的电子邮件(作为程序启动参数给出)。
您想多完美?
正如您可以使用不同的句子来表达一个谓词一样,您可以使用许多不同的正则表达式来定义相同的文本匹配规则。然而,此处提供的电子邮件验证表达式并不匹配所有可能的字符。例如,根据 RFC 2822(请参阅第 3.2.1、3.4.1 章),电子邮件地址的本地部分可以使用以下 ASCII 字符 ! # $ % * / ? | ^ { } ` ~ & ' + - = _
。另一方面,一些邮件系统则更具限制性。例如,Hotmail 只允许使用字母数字字符以及 . _ -
字符的电子邮件地址,并且会拒绝创建包含 ! # $ % * / ? | ^ { } ` ~ & ' + =
字符的电子邮件地址的邮件帐户或发送邮件。提供的验证表达式已考虑到兼容性问题,不应被视为通用的。您可以根据自己的特定需求自由修改它。
结论
尽管正则表达式通常是晦涩难懂且复杂的,但它们对于文本处理任务(如验证/约束用户输入、搜索和替换文本等)非常强大。试想一下,如果您必须用“正常”方式用“if
”语句来编写所有电子邮件匹配规则。代码将不是几行,而是大量“if
-else
”语句,这既不比这更具可读性,也不比这更少出错。这就是我现在想说的全部。因此,如果您发现本文有用,您可能想投它一票。 :)
修订历史
- 2015 年 5 月 23 日 现在支持长 TLD(顶级域)和以数字字符开头的域
- 2008 年 8 月 18 日 修正匹配表达式以匹配具有八位字节如 2[0-4][6-9] 的 IP 地址
- 2008 年 7 月 27 日 澄清表达式部分 1 已更正
- 2008 年 1 月 18 日 添加了 RFC 2822 文档的 Web 链接
- 2008 年 1 月 14 日 添加了修订历史
- 2008 年 1 月 12 日 添加了关于给定验证表达式与实际标准兼容性的考虑(请参阅“您想多完美?”)
- 2008 年 1 月 8 日 原始文章