验证电子邮件(不发送确认)

时间:2013-05-22 19:47:43

标签: java regex validation email-validation

验证电子邮件不是一个选项:(

我需要使用一组非常具体的规则来验证电子邮件地址。我已经尝试过Apache Commons库以及JavaMail库;虽然这两个都遵循RFC 2822,但根据我的规则,一些无效的电子邮件会通过。我一直在试试我的运气与regexes(regexi?)无济于事。我知道我知道。正则表达式不是最佳选择,可能会花费大量时间并增加复杂性。尽管如此,我认为,由于我的规则概述不是那么困难,因此为这个特定实例构建一个就足够了。

规则:

  1. 电子邮件地址的本地部分可能使用以下任意一项:
    • 大写和小写字母
    • 数字0-9
    • 特殊字符:,! #$%^& *()'`+ = - _ {} | 〜
    • 一段时间,但不能以句号开头或结尾
    • 可能不包含连续的句号
  2. 电子邮件的本地和域名部分之间必须有符号(@)
  3. 域名必须仅包含字母,数字,下划线,句点和连字符
    • 不能以连字符开头
    • 不能以连字符结尾
    • 不能包含两个连续的连字符
  4. 电子邮件的域名和TLD部分之间必须有一段时间
    • TLD必须只包含字母
    • TLD不得以句号结尾
  5. 到目前为止,我一直在尝试使用以下正则表达式:

    <德尔>     ^((\ {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来帮助我想象这个,因为我显然不是正则表达式大师。

2 个答案:

答案 0 :(得分:2)

我建议:

@符号上拆分。在最后一个时段拆分(使用String#substringString#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名称等),那么我的建议是:

  1. 将问题分解为更小的部分
  2. 为每个部分提供方法
  3. 验证每个部分(可能在循环中)。
  4. 使用正则表达式和标准逻辑的组合来确保它有效(根据您的规则)
  5. 这是留下一个合理的系统的唯一现实方法,这个系统可以被下次看到代码的可怜的傻瓜维护和理解。

    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 ....
      }
    }
    
相关问题