【问题标题】:Email Id validation according to RFC5322 and https://en.wikipedia.org/wiki/Email_address根据 RFC5322 和 https://en.wikipedia.org/wiki/Email_address 验证电子邮件 ID
【发布时间】:2019-04-17 08:54:31
【问题描述】:

根据 RFC5322 验证电子邮件 ID 并遵循

https://en.wikipedia.org/wiki/Email_address

以下是使用 java 和正则表达式验证电子邮件 ID 的示例代码。

public void checkValid() {
    List<String> emails = new ArrayList();
    //Valid Email Ids
    emails.add("simple@example.com");
    emails.add("very.common@example.com");                   
    emails.add("disposable.style.email.with+symbol@example.com");
    emails.add("other.email-with-hyphen@example.com");
    emails.add("fully-qualified-domain@example.com");
    emails.add("user.name+tag+sorting@example.com");
    emails.add("fully-qualified-domain@example.com");
    emails.add("x@example.com");
    emails.add("carlosd'intino@arnet.com.ar");
    emails.add("example-indeed@strange-example.com");
    emails.add("admin@mailserver1");
    emails.add("example@s.example");
    emails.add("\" \"@example.org");
    emails.add("\"john..doe\"@example.org");

    //Invalid emails Ids
    emails.add("Abc.example.com");
    emails.add("A@b@c@example.com");
    emails.add("a\"b(c)d,e:f;g<h>i[j\\k]l@example.com");
    emails.add("just\"not\"right@example.com");
    emails.add("this is\"not\\allowed@example.com");
    emails.add("this\\ still\"not\\allowed@example.com");
                    emails.add("1234567890123456789012345678901234567890123456789012345678901234+x@example.com");
    emails.add("john..doe@example.com");
    emails.add("john.doe@example..com");

    String regex = "^[a-zA-Z0-9_!#$%&'*+/=? \\\"`{|}~^.-]+@[a-zA-Z0-9.-]+$";

    Pattern pattern = Pattern.compile(regex);
    int i=0;
    for(String email : emails){
        Matcher matcher = pattern.matcher(email);
        System.out.println(++i +"."+email +" : "+ matcher.matches());
    }
}

实际输出:

   1.simple@example.com : true
   2.very.common@example.com : true
   3.disposable.style.email.with+symbol@example.com : true
   4.other.email-with-hyphen@example.com : true
   5.fully-qualified-domain@example.com : true
   6.user.name+tag+sorting@example.com : true
   7.fully-qualified-domain@example.com : true
   8.x@example.com : true
   9.carlosd'intino@arnet.com.ar : true
   10.example-indeed@strange-example.com : true
   11.admin@mailserver1 : true
   12.example@s.example : true
   13." "@example.org : true
   14."john..doe"@example.org : true
   15.Abc.example.com : false
   16.A@b@c@example.com : false
   17.a"b(c)d,e:f;g<h>i[j\k]l@example.com : false
   18.just"not"right@example.com : true
   19.this is"not\allowed@example.com : false
   20.this\ still"not\allowed@example.com : false
   21.1234567890123456789012345678901234567890123456789012345678901234+x@example.com    : true
   22.john..doe@example.com : true
   23.john.doe@example..com : true

预期输出:

1.simple@example.com : true
2.very.common@example.com : true
3.disposable.style.email.with+symbol@example.com : true
4.other.email-with-hyphen@example.com : true
5.fully-qualified-domain@example.com : true
6.user.name+tag+sorting@example.com : true
7.fully-qualified-domain@example.com : true
8.x@example.com : true
9.carlosd'intino@arnet.com.ar : true
10.example-indeed@strange-example.com : true
11.admin@mailserver1 : true
12.example@s.example : true
13." "@example.org : true
14."john..doe"@example.org : true
15.Abc.example.com : false
16.A@b@c@example.com : false
17.a"b(c)d,e:f;g<h>i[j\k]l@example.com : false
18.just"not"right@example.com : false
19.this is"not\allowed@example.com : false
20.this\ still"not\allowed@example.com : false
21.1234567890123456789012345678901234567890123456789012345678901234+x@example.com : false
22.john..doe@example.com : false
23.john.doe@example..com : false

如何更改我的正则表达式,以使以下电子邮件 ID 模式无效。

1234567890123456789012345678901234567890123456789012345678901234+x@example.com
john..doe@example.com
john.doe@example..com 
just"not"right@example.com

以下是正则表达式的标准:

本地部分

电子邮件地址的本地部分可以使用以下任何 ASCII 字符:

  1. 大写和小写拉丁字母A to Za to z
  2. 数字0 to 9;
  3. 特殊字符 !#$%&'*+-/=?^_`{|}~
  4. .,前提是它不是第一个或最后一个字符,除非 引用,并且还提供它不连续出现 除非引用(例如 John..Doe@example.com 是不允许的,但 "John..Doe"@example.com 是允许的);
  5. 允许使用 space"(),:;&lt;&gt;@[\] 字符,但有限制 (它们只允许在带引号的字符串中,如 下面的段落,此外,反斜杠或双引号必须 前面有一个反斜杠); cmets 允许带括号 在本地部分的任一端;例如 john.smith(comment)@example.com(comment)john.smith@example.com 都等价于 john.smith@example.com

  1. 大写和小写拉丁字母A to Za to z
  2. 数字0 to 9,前提是顶级域名不是 全数字;
  3. 连字符-,前提是它不是第一个或最后一个字符。 域和本地部分都允许评论;为了 例如,john.smith@(comment)example.comjohn.smith@example.com(comment) 相当于 john.smith@example.com.

【问题讨论】:

标签: java regex email-validation rfc5322


【解决方案1】:

你可以像这样RFC5322
(reference regex modified)

"(?im)^(?=.{1,64}@)(?:(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"@)|((?:[0-9a-z](?:\\.(?!\\.)|[-!#\\$%&'\\*\\+/=\\?\\^`\\{\\}\\|~\\w])*)?[0-9a-z]@))(?=.{1,255}$)(?:(\\[(?:\\d{1,3}\\.){3}\\d{1,3}\\])|((?:(?=.{1,63}\\.)[0-9a-z][-\\w]*[0-9a-z]*\\.)+[a-z0-9][\\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\\w]*))$"  

https://regex101.com/r/ObS3QZ/1

 # (?im)^(?=.{1,64}@)(?:("[^"\\]*(?:\\.[^"\\]*)*"@)|((?:[0-9a-z](?:\.(?!\.)|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)?[0-9a-z]@))(?=.{1,255}$)(?:(\[(?:\d{1,3}\.){3}\d{1,3}\])|((?:(?=.{1,63}\.)[0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\w]*))$

 # Note - remove all comments '(comments)' before runninig this regex
 # Find  \([^)]*\)  replace with nothing

 (?im)                                     # Case insensitive
 ^                                         # BOS

                                           # Local part
 (?= .{1,64} @ )                           # 64 max chars
 (?:
      (                                         # (1 start), Quoted
           " [^"\\]* 
           (?: \\ . [^"\\]* )*
           "
           @
      )                                         # (1 end)
   |                                          # or, 
      (                                         # (2 start), Non-quoted
           (?:
                [0-9a-z] 
                (?:
                     \.
                     (?! \. )
                  |                                          # or, 
                     [-!#\$%&'\*\+/=\?\^`\{\}\|~\w] 
                )*
           )?
           [0-9a-z] 
           @
      )                                         # (2 end)
 )
                                           # Domain part
 (?= .{1,255} $ )                          # 255 max chars
 (?:
      (                                         # (3 start), IP
           \[
           (?: \d{1,3} \. ){3}
           \d{1,3} \]
      )                                         # (3 end)
   |                                          # or,   
      (                                         # (4 start), Others
           (?:                                       # Labels (63 max chars each)
                (?= .{1,63} \. )
                [0-9a-z] [-\w]* [0-9a-z]* 
                \.
           )+
           [a-z0-9] [\-a-z0-9]{0,22} [a-z0-9] 
      )                                         # (4 end)
   |                                          # or,
      (                                         # (5 start), Localdomain
           (?= .{1,63} $ )
           [0-9a-z] [-\w]* 
      )                                         # (5 end)
 )
 $                                         # EOS

How make sudhansu_@gmail.com this as valid email ID – Mihir Feb 7 at 9:34

我认为规范希望本地部分用引号括起来
或者,用[0-9a-z] 包裹。

但是,要绕过后者并使sudhansu_@gmail.com 有效,只需
将第 2 组替换为:

      (                             # (2 start), Non-quoted
           [0-9a-z] 
           (?:
                \.
                (?! \. )
             |                              # or, 
                [-!#\$%&'\*\+/=\?\^`\{\}\|~\w] 
           )*
           @

      )                             # (2 end)

新的正则表达式

"(?im)^(?=.{1,64}@)(?:(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"@)|([0-9a-z](?:\\.(?!\\.)|[-!#\\$%&'\\*\\+/=\\?\\^`\\{\\}\\|~\\w])*@))(?=.{1,255}$)(?:(\\[(?:\\d{1,3}\\.){3}\\d{1,3}\\])|((?:(?=.{1,63}\\.)[0-9a-z][-\\w]*[0-9a-z]*\\.)+[a-z0-9][\\-a-z0-9]{0,22}[a-z0-9])|((?=.{1,63}$)[0-9a-z][-\\w]*))$"

新的演示

https://regex101.com/r/ObS3QZ/5

【讨论】:

  • 按预期工作。谢谢
  • 如何将sudhansu_@gmail.com 设为有效的电子邮件 ID
  • @Mihir - 为您添加了修复 ,,,
  • foo@bar%2ecom 应该是符合 RFC5322 的有效电子邮件吗?
【解决方案2】:

正则表达式是验证电子邮件地址最困难且最容易出错的方法。如果您使用javax.mail 的实现来发送电子邮件,那么确定它是否有效的最简单方法是使用提供的解析器,因为电子邮件是否符合要求,如果库不能使用它,那么它没关系。

public static boolean validateEmail(String address) {
    try {
        // if this fails, the mail library can't send emails to this address
        InternetAddress ia = new InternetAddress(address, true);
        return ia.isGroup() && ia.getAddress().charAt(0) != '@';
    }
    catch (Throwable t) {
        return false;
    }
}

使用false 调用它允许在严格解析时没有@domain 部分的电子邮件。而且由于内部调用的checkAddress 函数是私有的,我们不能只调用checkAddress(addr,false,true),因为我们不想要路由信息(实际上是为通过服务器弹跳进行欺诈而设计的功能),我们必须检查第一个字母验证地址。

现在您可能会注意到,此验证方法实际上符合 RFC 2822,而不是 5822。原因是除非您实现自己的 SMTP 发件人库,否则您使用的是依赖于这个,如果你有一个 5822 有效但 2822 无效的地址,那么你的 5822 验证将变得无用。但是如果你实现自己的 5822 SMTP 库,那么你应该学习现有的并编写一个解析器函数,而不是一个正则表达式。

【讨论】:

    【解决方案3】:

    这不是你问的问题,而是为什么要重新发明轮子?

    Apache commons has a class that covers this already.

    org.apache.commons.validator.routines.EmailValidator.getInstance().isValid(email)
    

    这样您就无需负责跟上不断变化的电子邮件格式标准。

    【讨论】:

    • Apache EmailValidator 根据 RFC 822 标准提供电子邮件地址验证。这里的问题是关于 RFC 5322。
    • JMail 是一个符合 RFC 5322 的新库,比 Apache Commons 更快、更正确。此外,它是可定制的,因此您可以将带有域文字(如 user@localhost)的地址视为无效。
    猜你喜欢
    • 2021-01-13
    • 2012-12-09
    • 2021-02-14
    • 2023-03-21
    • 1970-01-01
    • 2011-07-05
    • 2010-10-19
    • 1970-01-01
    • 2013-11-07
    相关资源
    最近更新 更多