regular expression for mail address


http://www.rfc-editor.org/rfc/rfc5336.txt に よるに mail address の 文字列は 次の如く 正規表現と し得るか。 (on Java)

```java
String obs_char = "[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]";
String obs_text = "\\n*\\r*(?:" + obs_char + "\\n*\\r*)*";
String text = "[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|(?:" + obs_text + ")";
String obs_qp = "\\\\[\\x00-\\x7f]";
String quoted_pair = "\\\\(?:" + text + ")|" + obs_qp;
String NO_WS_CTL = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]";
String qtext = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]";
String qcontent = qtext + "|" + quoted_pair;
String uqcontent = qcontent + "|[\\u0100-\\uffff]";
String uQuoted_string = "\"(?:" + uqcontent + ")*\"";
String atext = "[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]";
String ucharacter = "[-A-Za-z0-9!#$%&'*+/=?^_`{|}~\\u0100-\\uffff]";
String uAtom = ucharacter + "+";
String uDot_string = uAtom + "(?:\\." + uAtom + ")*";
String uLocal_part = uDot_string + "|" + uQuoted_string;

String Let_dig = "[A-Za-z0-9]";
String uLet_dig = "[A-Za-z0-9\\u0100-\\uffff]";
String uLdh_str = "[-A-Za-z0-9\\u0100-\\uffff]*" + uLet_dig;
String sub_udomain = uLet_dig + "(?:" + uLdh_str + ")?";
String Snum = "\\[0-9]{1,3}";
String Ldh_str = "[-A-Za-z0-9]*" + Let_dig;
String Standardized_tag = Ldh_str;
String dcontent = text + "|" + quoted_pair;
String General_address_literal = Standardized_tag + ":(?:" + dcontent + ")+";
String IPv6_hex = "[0-9A-Fa-f]{1,4}";
String IPv4_address_literal = Snum + "(?:\\." + Snum + "){3}";
String IPv6v4_comp = "(?:" + IPv6_hex + "(?::" + IPv6_hex + "){0,3})?::(?:" + IPv6_hex + "(?::" + IPv6_hex + "){3}:)?" + IPv4_address_literal;
String IPv6v4_full = IPv6_hex + "(?::" + IPv6_hex + "){5}:" + IPv4_address_literal;
String IPv6_comp = "(?:" + IPv6_hex + "(?::" + IPv6_hex + "){0,5})?::(?:" + IPv6_hex + "(?:" + IPv6_hex + "){0,5})?";
String IPv6_full = IPv6_hex + "(?::" + IPv6_hex + "){7}";
String IPv6_addr = IPv6_full + "|" + IPv6_comp + "|" + IPv6v4_full + "|" + IPv6v4_comp;
String IPv6_address_literal = "IPv6:(?:" + IPv6_addr + ")";
String address_literal = "\\[(?:(?:" + IPv4_address_literal + ")|(?:" + IPv6_address_literal + ")|(?:" + General_address_literal + "))\\]";
String uDomain = "(?:" + sub_udomain + "(?:\\." + sub_udomain + ")+)|(?:" + address_literal + ")";

String uMailbox = "(?:" + uLocal_part + ")@(?:" + uDomain + ")";
```

この uMailbox につき

```java
Pattern pattern = Pattern.compile(uMailBox);
Matcher matcher = pattern.matcher(address);
if (matcher.match()) {
    // OK
} else {
    // NG
}
```

uMailbox は flat なる string literal とするに

```java
String uMailbox = "(?:[-A-Za-z0-9!#$%&'*+/=?^_`{|}~\\u0100-\\uffff]+(?:\\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~\\u0100-\\uffff]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\(?:[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|(?:\\n*\\r*(?:[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]\\n*\\r*)*))|\\\\[\\x00-\\x7f]|[\\u0100-\\uffff])*\")@(?:(?:[A-Za-z0-9\\u0100-\\uffff](?:[-A-Za-z0-9\\u0100-\\uffff]*[A-Za-z0-9\\u0100-\\uffff])?(?:\\.[A-Za-z0-9\\u0100-\\uffff](?:[-A-Za-z0-9\\u0100-\\uffff]*[A-Za-z0-9\\u0100-\\uffff])?)+)|(?:\\[(?:(?:\\[0-9]{1,3}(?:\\.\\[0-9]{1,3}){3})|(?:IPv6:(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){7}|(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){0,5})?::(?:[0-9A-Fa-f]{1,4}(?:[0-9A-Fa-f]{1,4}){0,5})?|[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){5}:\\[0-9]{1,3}(?:\\.\\[0-9]{1,3}){3}|(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){0,3})?::(?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4}){3}:)?\\[0-9]{1,3}(?:\\.\\[0-9]{1,3}){3}))|(?:[-A-Za-z0-9]*[A-Za-z0-9]:(?:[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|(?:\\n*\\r*(?:[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]\\n*\\r*)*)|\\\\(?:[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|(?:\\n*\\r*(?:[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]\\n*\\r*)*))|\\\\[\\x00-\\x7f])+))\\]))";
```

この matcher は 次は通し

```java
"Abc@example.com"
"Abc.123@example.com"
"user+mailbox/department=shipping@example.com"
"!#$%&'*+-/=?^_`.{|}~@example.com"
"\"Abc@def\"@example.com"
"\"Fred\\ Bloggs\"@example.com"
"\"Joe.\\\\Blow\"@example.com"
"ほげほげ@ほげ.jp"
```

次は通さず

```java
"Abc"
" Abc@example.com"
"Abc@examle.com "
"Abc.@example.com"
"Abc..123@example.com"
```

下の 二つは 昔の docomo にて 許しつる patterns にて @ の 直前に . の 有るものと 連續する 複數の . の 有るものなり。 いづれも RFC 違反なり。
これを 通すには たとへば

```java
address = address
        .replaceAll("((?:\\.){2,})", Matcher.quoteReplacement(".")
        .replaceAll("\\.@", "@");
```

などゝ せば よろしからむ。

なほ JavaScript にては

```javascript
var re = new RegExp(uMailbox);

address = address.replace(/(?:\.){2,}/g, '.').replace(/\.@/, '@');

if (re.test(address)) {
    // OK
} else {
    // NG
}
```