区分电子邮件地址与IRI的算法正确性验证及扩展至IP地址的问询
区分电子邮件地址、IRI与IP地址的算法分析
原算法的正确性分析
你的思路方向是对的,但存在几个边缘场景的漏洞,不能完全覆盖所有合法情况:
- 正确的部分:
- 以引号开头的字符串必然是电子邮件地址:没错,RFC 3987规定IRI的scheme部分必须以字母开头,后续只能是字母、数字、
+、-、.,不可能包含引号;而RFC 5322允许邮箱本地部分使用带引号的字符串(比如"john.doe"@example.com),这一步判定是可靠的。
- 以引号开头的字符串必然是电子邮件地址:没错,RFC 3987规定IRI的scheme部分必须以字母开头,后续只能是字母、数字、
- 漏洞场景:
- 带权威部分的相对IRI:比如
//user@example.com,这是合法的IRI,但它既不以引号开头,也不含:,原算法会找到@并误判为邮箱地址。 - 不含scheme的相对IRI包含@:比如
path@to/resource,这是合法的相对IRI(RFC 3987允许路径段包含@),但原算法会因为第一个特殊字符是@而误判为邮箱。 - 无@和:的IRI:比如
/docs/readme这类根路径相对IRI,原算法找不到@或:,无法做出有效判定。
- 带权威部分的相对IRI:比如
更简便的优化方案
基于“字符串仅为邮箱或IRI”的前提,可以调整为更准确的两步判定:
- 先判断是否为IRI:
检查字符串是否符合以下任一情况:- 包含合法的scheme部分:即存在一个
:,且:之前的字符符合RFC 3987的scheme规则(以字母开头,后续是字母、数字、+、-、.),比如https://example.com、mailto:user@example.com。 - 是相对IRI:不以字母开头(避免和邮箱混淆),且符合相对IRI的格式(比如以
/、//开头,或包含路径分隔符/)。
- 包含合法的scheme部分:即存在一个
- 否则判定为电子邮件地址:
剩下的情况必然是包含且仅包含一个@,且@不在字符串首尾(符合RFC 5322的邮箱核心结构)。
如果追求极致简便,还可以简化为:如果字符串包含一个符合scheme规则的:,则为IRI;否则如果包含@,则为邮箱;其余情况为相对IRI(前提是字符串仅属于这两类)。
扩展区分IP地址的方案
要加入IPv4和IPv6的区分,可以在原有判定前增加一步IP校验:
- 第一步:判断是否为IP地址:
- 若字符串以
[开头且以]结尾:尝试解析为IPv6地址(验证内部是否符合IPv6的十六进制段格式,比如[2001:db8::1])。 - 否则:检查是否符合IPv4的点分四段格式(每段为0-255的整数,比如
192.168.1.1)。
- 若字符串以
- 第二步:再区分邮箱和IRI:
排除IP地址后,用前面优化后的算法判定剩余的字符串类型。
内容的提问来源于stack exchange,提问作者Garret Wilson




