我需要使用一组非常具体的规则来验证电子邮件地址。我已经尝试过Apache Commons库以及JavaMail库;虽然这两个都遵循RFC 2822,但根据我的规则,一些无效的电子邮件会通过。我一直在试试我的运气与regexes(regexi?)无济于事。我知道我知道。正则表达式不是最佳选择,可能会花费大量时间并增加复杂性。尽管如此,我认为,由于我的规则概述不是那么困难,因此为这个特定实例构建一个就足够了。
到目前为止,我一直在尝试使用以下正则表达式:
<德尔> ^((\ {2})[^] [ - A-ZA-Z0-9 _ \ \ @ \#\ $ \%\ ^ \&放大器;?!。!\ * \(\)\ ,\'\ + \ = \'\ {\ | \}。\〜\ - ] + [^])@(?!。。(\ - {2})[^ -_] [ - α-ZA -Z0-9 _。] + [^ -_] \ [A-ZA-Z] +)$ 德尔>
^((?!.\.{2,}.)[^.][-a-zA-Z0-9_.!@#$%^&*(),'+=`{|}~-]+[^.])@((?!.\-{2,}.)[^-_][-a-zA-Z0-9_.]+[^-_]\.[a-zA-z]+)$
使用无效的电子邮件仍然失败(例如justlikethat@gm--ail.com)。
我对正则表达式遗漏或做错了什么?有没有其他方法可以确保电子邮件符合要求而无需正则表达式?
提前致谢!
P.S。这是Java中的,因此上述正则表达式中的所有转义字符都必须进行双重转义(例如\.
为\\.
)。我一直在使用Regexper来帮助我想象这个,因为我显然不是正则表达式大师。
答案 0 :(得分:2)
我建议:
在@
符号上拆分。在最后一个时段拆分(使用String#substring
和String#lastIndexOf
)。现在,您将本地部分,域和TLD都放在单独的字符串中,使用if语句进行验证。如果有适用于所有规则的任何规则(连续2个?),请在拆分之前执行此操作。更容易理解,更容易理解,维护起来更简单。
但是,如果你真的想坚持正则表达式,这里有一些我见过的东西:
[^.]
之前的@
应为(?<!\.)
,否则@
之前的最后一个字符可以是任何内容。
.
只有一个字符,因此(?!.\-{2,}.)
和(?!.\.{2,}.)
不会按照您的想法执行。只是让它.*
似乎解决了它。而且你不需要在你想要的东西之后检查任何字符。
尚未明确说明,但我认为域和TLD也不能包含2个连续的期间。如果允许,则正则表达式的第一部分需要(?!.*\.{2,}.*@)
才能停在@
。
如果您使用String#matches
,则不需要^
和$
。
有一些不需要的()
。
最终正则表达式:
(?!.*\.{2,})[^.][-a-zA-Z0-9_.!@#$%^&*(),'+=`{|}~-]+(?<!\.)@(?!.*\-{2,})[^-_][-a-zA-Z0-9_.]+[^-_]\.[a-zA-z]+
如果您选择坚持正则表达式,我建议广泛评论:
String regex =
"(?!.*\\.{2,})" // doesn't contain 2 consecutive .'s
// local part
+ "[^.]" // doesn't start with a .
+ "[-a-zA-Z0-9_.!@#$%^&*(),'+=`{|}~-]+" // valid chars for local part
+ "(?<!\\.)" // last char of local part isn't a .
// at symbol
+ "@"
// domain
...
这可能看起来有点矫枉过正,但是如果你试图在几个月之后保持这种状态,你会希望如此,特别是如果你在那几个月没有触及任何正则表达式的话。
答案 1 :(得分:1)
普遍的看法是,电子邮件对于单个正则表达式而言过于复杂。通过查看SMTP服务器是否可以发送它来检查电子邮件地址更容易。你已经被告知了。
因此,假设您需要预先验证地址(并假设它只是电子邮件部分,而不是所有的好东西,您可以拥有像unicode名称等),那么我的建议是:
这是留下一个合理的系统的唯一现实方法,这个系统可以被下次看到代码的可怜的傻瓜维护和理解。
e.g。
private void validateNamePart(String npart) {
if (!npart.matches("")) {
throw new .....;
}
}
private void validateName(String name) {
int parts = 0;
for (String npart : name.split("\\.")) {
validateNamePart(npart);
parts++;
}
if (parts == 0) {
throw ....;
}
}
private void validateDomainPart(String dpart) {
....
}
private void validateDomain(String domain) {
....
}
public void validateEMail(String email) {
String parts = email.split("@");
if (parts.length == 2) {
validateName(parts[0]);
validateDomain(parts[1]);
} else {
throw ....
}
}