不支持lookaround的Sieve环境下,匹配排除特定local part的邮箱正则
需求与问题描述
我需要一个正则表达式,匹配特定域名domain.tld的所有邮箱地址,但排除本地部分(local part)为fritzbox的地址。但我使用的邮件服务器Sieve引擎不支持任何环视(lookaround)。
我查阅过相关资料,见过一个匹配所有不以foo开头的字符串的示例:
^(([^f].{2}|.[^o].|.{2}[^o]).*|.{0,2})$
但没法把这个逻辑适配到「排除fritzbox@domain.tld,匹配其他xxx@domain.tld」的场景,也搞不懂示例里{2}和{0,2}的作用。
我盲目尝试了下面的正则,但无法正常工作:
^(([^f].{7}|.[^r].|.[^i].|.[^t].|.[^z].|.[^b].|.[^o].|.{7}[^x]).*|.{0,7})@domain\.tld$
我知道可以用Sieve的非正则写法:
if allof (address :domain :matches "from" "domain.tld", not address :localpart :is "from" "fritzbox") { do something; }
但这需要单独创建规则,我希望把这个条件和其他anyof条件合并,所以更倾向于用正则实现。
求可行的正则方案及原理说明?
可行正则方案
适合Sieve无环视环境的正则如下:
^(?:.{0,7}|.{9,}|[^f].{7}|f[^r].{6}|fr[^i].{5}|fri[^t].{4}|frit[^z].{3}|fritz[^b].{2}|fritzb[^o].|fritzbo[^x])@domain\.tld$
原理说明
这个正则的核心是通过正向匹配穷举所有「localpart不等于fritzbox」的可能,因为不支持环视,只能用这种方式排除目标地址:
长度不匹配的情况:
.{0,7}:匹配长度0-7的任意localpart,直接排除了长度为8的fritzbox.{9,}:匹配长度9及以上的任意localpart,同样不可能等于fritzbox
长度匹配但字符不匹配的情况:
针对fritzbox的8个字符位置,逐个构造「前缀匹配+当前位不匹配+剩余任意字符」的规则:[^f].{7}:第1位不是f,后面7位任意(总长度8)f[^r].{6}:第1位是f,第2位不是r,后面6位任意fr[^i].{5}:前2位是fr,第3位不是i,后面5位任意fri[^t].{4}:前3位是fri,第4位不是t,后面4位任意frit[^z].{3}:前4位是frit,第5位不是z,后面3位任意fritz[^b].{2}:前5位是fritz,第6位不是b,后面2位任意fritzb[^o].:前6位是fritzb,第7位不是o,最后1位任意fritzbo[^x]:前7位是fritzbo,第8位不是x
将所有这些情况用|组合,再加上固定的@domain\.tld后缀,就能精准匹配所有domain.tld域名下、localpart不是fritzbox的邮箱地址。
内容的提问来源于stack exchange,提问作者myfxp
相关产品推荐
相关产品推荐

