正则表达式根据 RFC2822 验证消息 ID
Posted
技术标签:
【中文标题】正则表达式根据 RFC2822 验证消息 ID【英文标题】:regex to validate a message-ID as per RFC2822 【发布时间】:2011-04-27 11:29:18 【问题描述】:我还没有找到执行此操作的正则表达式。我需要验证电子邮件中的“Message-ID:”值。它类似于电子邮件地址验证正则表达式,但更简单,没有电子邮件地址允许的大多数边缘情况,来自rfc2822
msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
id-left = dot-atom-text / no-fold-quote / obs-id-left
id-right = dot-atom-text / no-fold-literal / obs-id-right
no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE
no-fold-literal = "[" *(dtext / quoted-pair) "]"
假设外部 是可选的。点原子文本和缺失的定义可以在rfc2822中找到
我不精通正则表达式,我更喜欢使用已经测试过的,如果存在的话。
【问题讨论】:
找到了吗?那么,尝试自己写一个怎么样? :) 【参考方案1】:尝试类似 --> ^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]2,$
【讨论】:
这不正确,它不完全像一个电子邮件地址,@后面的部分不需要是'something.something'【参考方案2】:由于我找不到任何东西,我最终自己实现了它。根据 RFC2822,这不是一个正确的验证,但目前已经足够接近:
static String VALIDMIDPATTERN = "[a-z0-9!#$%&'*+/=?^_`|~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`|~-]+)*@[a-z0-9!#$%&'*+/=?^_`|~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`|~-]+)*";
private static Pattern patvalidmid = Pattern.compile(VALIDMIDPATTERN);
public static boolean isMessageIdValid(String midt)
String mid = midt;
if (StringUtils.countMatches(mid, "<") > 1)
return false;
if (StringUtils.countMatches(mid, ">") > 1)
return false;
if (StringUtils.containsAny(mid, "<>"))
mid = StringUtils.substringBetween(mid, "<", ">");
if (StringUtils.isBlank(mid))
return false;
if (StringUtils.contains(mid, ".."))
return false;
//extract from <>
mid = mid.trim();
//now validate
Matcher m = patvalidmid.matcher(mid);
return m.matches();
【讨论】:
这个正则表达式是否只涵盖id-left
和id-right
的dot-atom-text
部分?我认为obs-id-left
将允许几乎任何 ASCII 字符。
@Nathan:很久以前……不记得了。可能你是对的,但我可以告诉你这个 impl。已成功用于处理商业产品中的数百万条消息 ID。所以使用起来应该是安全的。
感谢您确认您的生产使用情况 - 这有助于确认 id-left 和 id-right 的引用和过时部分实际上并未在实践中使用。【参考方案3】:
使用标准正则表达式无法完美匹配 RFC2822 消息 ID,因为 CFWS 规则允许嵌套 cmets,这是正则表达式无法处理的。例如
<foo@bar.com> (comment (another comment))
【讨论】:
不正确。嵌套模式可以与递归正则表达式匹配。【参考方案4】:如果有人感兴趣,我们的一位高级架构师研究了 RFC 2822 的多个层次,并提出了以下正则表达式,其中包括在左侧和右侧的引用。规范说新的实现不应该使用过时的字符,所以这个正则表达式不允许它们:
((([a-zA-Z0-9!#$%&'*+/=?^_`|~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`|~-]+)*)|("(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(([a-zA-Z0-9!#$%&'*+/=?^_`|~-]+(\.[a-zA-Z0-9!#$%&'*+/=?^_`|~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))
【讨论】:
这是一个带有不匹配组的 Python 正则表达式字符串:r'((?:(?:[a-zA-Z0-9!#$%&\'*+/=?^_`|~-]+(?:\.[a-zA-Z0-9!#$%&\'*+/=?^_`|~-]+)*)|(?:"(?:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(?:(?:[a-zA-Z0-9!#$%&\'*+/=?^_`|~-]+(?:\.[a-zA-Z0-9!#$%&\'*+/=?^_`|~-]+)*)|(?:\[(?:(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21-\x5A\x5E-\x7E])|(?:\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))'
以上是关于正则表达式根据 RFC2822 验证消息 ID的主要内容,如果未能解决你的问题,请参考以下文章
根据 RFC5321/RFC5322 对电子邮件地址进行正则表达式验证