정규식을 사용하여 이메일 주소를 확인하는 방법은 무엇입니까?


3311

지난 몇 년 동안 나는 IP 주소를 서버 부분으로 사용하지 않는다고 가정하면서 MOST 전자 메일 주소의 유효성을 올바르게 검사 하는 정규식 을 천천히 개발했습니다 .

여러 PHP 프로그램에서 사용하며 대부분 작동합니다. 그러나 때때로 나는 그것을 사용하는 사이트에 문제가있는 누군가와 연락을 취하고 조정해야합니다 (가장 최근에는 4 자 TLD를 허용하지 않는다는 것을 깨달았습니다).

이메일 확인에있어 가장 좋은 정규 표현은 무엇입니까?

여러 개의 짧은 표현식을 사용하는 함수를 사용하는 여러 솔루션을 보았지만 더 복잡한 함수의 여러 짧은 표현식 대신 간단한 함수에서 하나의 긴 복잡한 표현식을 사용하고 싶습니다.



5
IDNA의 형식이 올바른지 검증 할 수있는 정규식이 stackexchange에 맞지 않습니다. (정규화에 대한 규칙은 정말 비참하고 특히 정규식 처리에 적합하지 않습니다)
Jasen


정규 표현식은 경우에 따라 가변적 일 수 있으며 , 이메일 콘은 공백을 포함 할 수 있으며 다른 경우에는 공백을 포함 할 수 없습니다.
Ṃųỻịgǻňạcểơửṩ

답변:


2439

완전히 RFC 822 호환 정규 표현식은 비효율적 때문에 길이의 불분명. 다행히 RFC 822가 두 번 대체되었으며 현재 이메일 주소 사양은 RFC 5322 입니다. RFC 5322는 몇 분 동안 연구하면 이해할 수 있고 실제 사용하기에 충분히 효율적인 정규식으로 이어집니다.

하나의 RFC 5322 호환 정규 표현식은 http://emailregex.com/ 페이지 상단에서 찾을 수 있지만 00부호없는 바이트 10 진수 값 을 허용하는 버그로 인터넷 주위에 떠있는 IP 주소 패턴을 사용합니다 . 점으로 구분 된 주소로, 불법입니다. 나머지는 RFC 5322 문법과 일치하는 것으로 보이며 grep -Po도메인 이름, IP 주소, 잘못된 것, 따옴표가 있거나없는 계정 이름 등을 사용하여 몇 가지 테스트를 통과했습니다 .

00IP 패턴 의 버그를 수정하여 작동하고 상당히 빠른 정규식을 얻습니다. (실제 코드의 경우 마크 다운이 아닌 렌더링 된 버전을 폐기합니다.)

(? : [a-z0-9! # $ % & '* + / =? ^ _`{|} ~-] + (? : \. [a-z0-9! # $ % &'* + / =? ^ _`{|} ~-] +) * | "(? : [\ x01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21 \ x23- \ x5b \ x5d- \ x7f] | \\ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f]) * ") @ (? : (? : [a-z0-9] (? : [a-z0-9-] * [a-z0) -9])? \.) + [a-z0-9] (? : [a-z0-9-] * [a-z0-9])? | \ [(? :(? :( 2 (5 [0-5] | [0-4] [0-9]) | 1 [0-9] [0-9] | [1-9]? [0-9])) \.) {3} ( ? :( 2 (5 [0-5] | [0-4] [0-9]) | 1 [0-9] [0-9] | [1-9]? [0-9]) | [ a-z0-9-] * [a-z0-9] : (? : [\ x01- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x21- \ x5a \ x53- \ x7f] | \\ [\ x01- \ x09 \ x0b \ x0c \ x0e- \ x7f]) +) \])

또는:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

다음은 정규 표현식 자체보다 명확한 정규 표현식 위 의 유한 상태 머신 다이어그램 입니다.여기에 이미지 설명을 입력하십시오

Perl 및 PCRE의보다 정교한 패턴 (예 : PHP에서 사용되는 정규식 라이브러리)은 장애없이 RFC 5322를 올바르게 구문 분석 할 수 있습니다 . 파이썬과 C #도 그렇게 할 수 있지만 처음 두 가지와 다른 구문을 사용합니다. 그러나 덜 강력한 패턴 일치 언어 중 하나를 사용해야하는 경우 실제 구문 분석기를 사용하는 것이 가장 좋습니다.

또한 RFC에 따라 유효성을 검사하면 해당 주소가 제공된 도메인에 실제로 존재하는지 또는 주소를 입력 한 사람이 실제 소유자인지 여부를 전혀 알 수 없음을 이해하는 것이 중요합니다. 사람들은 항상 이런 방식으로 다른 사람들에게 메일 링리스트에 서명합니다. 주소와 동일한 웹 페이지에 입력되어야하는 확인 토큰을 포함하는 메시지를 해당 주소로 전송하는 것과 같은보다 강력한 종류의 유효성 검사가 필요한 수정.

확인 토큰은 입력 한 사람의 주소를 알 수있는 유일한 방법입니다. 이것이 대부분의 메일 링리스트가 가입을 확인하기 위해이 메커니즘을 사용하는 이유입니다. 결국, 누구나 내려 놓을 수 있고 president@whitehouse.gov, 그것은 합법적으로 파싱 될 것이지만, 다른 쪽 사람은 아닐 것입니다.

PHP의 경우 PHP 로 전자 메일 주소 확인에 제공된 패턴을 사용 해서는 안됩니다 .

일반적인 사용법과 광범위하게 조잡한 코딩이 기록 된 공식 표준보다 더 제한적인 전자 메일 주소에 대한 사실상의 표준을 확립 할 위험이 있습니다.

그것은 다른 모든 비 RFC 패턴보다 낫지 않습니다. RFC 5322는 물론 RFC 822 조차도 처리하기에 충분히 똑똑하지는 않습니다 . 그러나 이것은 하나 입니다.

화려하고 번거롭기를 원한다면 완전한 상태 엔진을 구현하십시오 . 정규식은 기초 필터로만 작동 할 수 있습니다. 정규 표현식의 문제점은 정규 표현식이 처리 할 수 ​​없기 때문에 완벽하게 유효한 전자 메일 주소가 유효하지 않다고 잘못 판단한다는 것입니다 (사용자의 입장에서는 무례하고 무례합니다). 목적을위한 상태 엔진은 각 RFC에 따라 전자 우편 주소를 분해 할 때 유효하지 않은 전자 우편 주소를 검증하고 정정 할 수 있습니다. 이것은 잠재적으로 더 즐거운 경험을 허용합니다.

지정된 이메일 주소 'myemail @ address, com'이 유효하지 않습니다. 'myemail@address.com'을 의미 했습니까?

주석을 포함하여 이메일 주소 확인 도 참조하십시오 . 또는 정규식 확인 이메일 주소 비교 .

정규식 시각화

Debuggex 데모


179
"정규 표현이 좋지 않습니다." 이것은 일반적이거나 전자 메일 주소 확인에만 해당됩니까?
Tomalak

37
@Tomalak : 이메일 주소에만 해당됩니다. bortzmeyer가 말했듯이 RFC는 매우 복잡합니다.
Luk

37
언급 한 리눅스 저널 기사는 사실 여러면에서 잘못되었습니다. 특히 Lovell은 RFC3696에 대한 정오표를 명확하게 읽지 않았으며 RFC의 게시 된 버전에서 일부 오류를 반복합니다. 자세한 내용은 여기 : dominicsayers.com/isemail
Dominic Sayers

9
Jeff Atwood는이 블로그 게시물에 모든 유효한 이메일 주소를 확인하는 멋진 정규식을 가지고 있습니다 : codinghorror.com/blog/2005/02/regex-use-vs-regex-abuse.html
CMircea

5
참고 현재 HTML5 스펙이 의도적으로 더 제한적인 원래의 RFC보다 이메일 형 입력 검증을위한 정규식과 ABNF가 포함되어 있습니다.
Synchro

746

이메일 주소의 유효성을 검사하기 위해 정규식을 사용해서는 안됩니다.

대신 다음과 같이 MailAddress 클래스를 사용하십시오 .

try {
    address = new MailAddress(address).Address;
} catch(FormatException) {
    // address is invalid
}

MailAddress클래스는 BNF 파서를 사용하여 RFC822에 따라 주소의 전체 유효성을 검사합니다.

를 사용하여 MailAddress전자 메일 주소의 유효성을 검사하려는 경우이 방법 을 사용하면 전자 메일 주소의 표시 이름 부분도 허용되므로 정확하게 달성하려는 것이 아닐 수도 있습니다. 예를 들어 다음 문자열을 유효한 전자 메일 주소로 허용합니다.

  • "user1@hotmail.com; user2@gmail.com"
  • "user1@hotmail.com; user2@gmail.com; user3@company.com"
  • "사용자 표시 이름 user3@company.com"
  • "user4 @ company.com"

이러한 경우 중 일부에서는 문자열의 마지막 부분 만 주소로 구문 분석됩니다. 그 전의 나머지는 표시 이름입니다. 표시 이름없이 일반 전자 메일 주소를 얻으려면 정규화 된 주소를 원래 문자열과 비교하여 확인할 수 있습니다.

bool isValid = false;

try
{
    MailAddress address = new MailAddress(emailAddress);
    isValid = (address.Address == emailAddress);
    // or
    // isValid = string.IsNullOrEmpty(address.DisplayName);
}
catch (FormatException)
{
    // address is invalid
}

또한, 끝에 같은 점이있는 주소도 user@company.MailAddress에 의해 허용됩니다.

당신이 정말로 정규식을 사용하려면, 여기있다 :

(? : (? : \ r \ n)? [\ t]) * (? : (? : (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031 ] + (? : (? : (? : \ r \ n)? [\ t]
) + | \ Z | (? = [\ [ "() <> @,; :: \\". \ [\]])) | "(? : [^ \"\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) * "(? :( ?:
\ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \ \ ". \ [\] \ 000- \ 031] + (? :(? :(
? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | "(? : [ ^ \ "\ r \\] | \\. | (? : (? : \ r \ n)? [ 
\ t])) * "(? : (? : \ r \ n)? [\ t]) *)) * @ (? : (? : \ r \ n)? [\ t]) * (?: [^ () <> @,; : \\ ". \ [\] \ 000- \ 0
31] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\ ]])) | \ [([^ \ [\] \ r \\] | \\.) * \
] (? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] +
(? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; :: \\". \ [\]]) ) | \ [([^ \ [\] \ r \\] | \\.) * \] (?:
(? : \ r \ n)? [\ t]) *)) * | (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (?: (? : (? : \ r \ n)? [\ t]) + | \ Z
| (? = [\ [ "() <> @,; : \\". \ [\]])) | "(? : [^ \"\ r \\] | \\. | (? :( ? : \ r \ n)? [\ t])) * "(? : (? : \ r \ n)
? [\ t]) *) * \ <(? : (? : \ r \ n)? [\ t]) * (? : @ (? : [^ () <> @,; : \\ "). \ [\] \ 000- \ 031] + (? : (? : (? : \
r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; :: \\". \ [\]])) | \ [([^ \ [\ ] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [
 \ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)
? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | \ [([^ \ [\] \ r \ \] | \\.) * \] (? : (? : \ r \ n)? [\ t]
) *)) * (? : ,, @ (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [
 \ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *
) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031 ] + (? : (? : (? : \ r \ n)? [\ t]
) + | \ Z | (? = [\ [ "() <> @,; :: \\". \ [\]])) | \ [([^ \ [\] \ r \\] | \\ .) * \] (? : (? : \ r \ n)? [\ t]) *)) *)
* : (? : (? : \ r \ n)? [\ t]) *)? (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) +
| \ Z | (? = [\ [ "() <> @,; : \\". \ [\]]))] "(? : [^ \"\ r \\] | \\. | ( ? : (? : \ r \ n)? [\ t])) * "(? : (? : \ r
\ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ " . \ [\] \ 000- \ 031] + (? :(? :( ?:
\ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]]))] ((:: [^ \ "\ r \\] | \\. | (? : (? : \ r \ n)? [\ t
])) * "(? : (? : \ r \ n)? [\ t]) *)) * @ (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031
] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\] ])) | \ [([^ \ [\] \ r \\] | \\.) * \] (
? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (?
: (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? :(?
: \ r \ n)? [\ t]) *)) * \> (? : (? : \ r \ n)? [\ t]) *) | (? : [^ () <> @ ,; : \\ ". \ [\] \ 000- \ 031] + (? :(?
: (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | "(? : [^ \ "\ r \\] | \\. | (? : (? : \ r \ n)?
[\ t])) * "(? : (? : \ r \ n)? [\ t]) *) * : (? : (? : \ r \ n)? [\ t]) * (?: (? : (? : [^ () <> @,; : \\ ". \ [\] 
\ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\" . \ [\]])) | "(? : [^ \"\ r \\] |
\\. | (? : (? : \ r \ n)? [\ t])) * "(? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <>

@,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | "
(? : [^ \ "\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) *"(? : (? : \ r \ n)? [ \ t]) *)) * @ (? : (? : \ r \ n)? [\ t]
) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\
". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : (? : \ r \ n)? [\ t]) * ) (? : \. (? : (? : \ r \ n)? [\ t]) * (?
: [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [
\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) * | (? : [^ () <> @,; : \\ ". \ [\] \ 000-
\ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [ \]])) | "(? : [^ \"\ r \\] | \\. | (
? : (? : \ r \ n)? [\ t])) * "(? : (? : \ r \ n)? [\ t]) *) * \ <(? : (? : \ r \ n)? [\ t]) * (? : @ (? : [^ () <> @ ,;
: \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ ["() <> @,; : \\ ". \ [\]])) | \ [([
^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ "
. \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @, ; : \\ ". \ [\]])) \ [([^ \ [\
] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) * (? :, @ (? : (? : \ r \ n )? [\ t]) * (? : [^ () <> @,; : \\ ". \
[\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\ ". \ [\]])) | \ [([^ \ [\] \
r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] 
\ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\" . \ [\]])) | \ [([^ \ [\] \ r \\]
| \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) *) * : (? : (? : \ r \ n)? [\ t]) * )? (? : [^ () <> @,; : \\ ". \ [\] \ 0
00- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\]])) | "(? : [^ \"\ r \\] | \\
. | (? : (? : \ r \ n)? [\ t])) * "(? : (? : (? : \ r \ n)? [\ t]) *) (? : \. (? :( ? : \ r \ n)? [\ t]) * (? : [^ () <> @,
; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ ["( ) <> @,; : \\ ". \ [\]]))" "(?
: [^ \ "\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) *"(? : (? : \ r \ n)? [\ t ]) *)) * @ (? : (? : \ r \ n)? [\ t]) *
(? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\".
\ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *) ( ? : \. (? : (? : \ r \ n)? [\ t]) * (? : [
^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | ( ? = [\ [ "() <> @,; : \\". \ [\]
])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) * \> ( ? : (? : \ r \ n)? [\ t]) *) (? :, \ s * (
? : (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\
". \ [\]])) |"(? : [^ \ "\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) *"(? : (? : \ r \ n)? [\ t]) *) (? : \. (? :(
? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? :(? :(? : \ r \ n)? [\ t]) + | \ Z | (? = [
\ [ "() <> @,; : \\". \ [\]]))] "(? : [^ \"\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) * "(? : (? : \ r \ n)? [\ t
]) *)) * @ (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n) ?? [\ t
]) + | \ Z | (? = [\ [ "() <> @,; :: \\". \ [\]])) | \ [([^ \ [\] \ r \\]] \ \.) * \] (? : (? : \ r \ n)? [\ t]) *) (?
: \. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + ( ? : (? : (? : \ r \ n)? [\ t]) + |
\ Z | (? = [\ [ "() <> @,; :: \\". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) * | (?:
[^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\". \ [\
]]))] "(? : [^ \"\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) * "(? : (? : \ r \ n)? [\ t]) *) * \ <(? : (? : \ r \ n)
? [\ t]) * (? : @ (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "
() <> @,; :: \\ ". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)
? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <>

@,; : \\ ". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) * (? :, @ (? : (? : \ r \ n)? [
 \ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,
; : \\ ". \ [\]]))] \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *) (? : \. (? : (? : \ r \ n)? [\ t]
) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\
". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : (? : \ r \ n)? [\ t]) * )) *) * : (? : (? : \ r \ n)? [\ t]) *)?
(? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [ "() <> @,; : \\".
\ [\]])) | "(? : [^ \"\ r \\] | \\. | (? : (? : \ r \ n)? [\ t])) * "(? :( ? : \ r \ n)? [\ t]) *) (? : \. (? :( ?:
\ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t]) + | \ Z | (? = [\ [
"() <> @,; : \\". \ [\]]))] "(? : [^ \"\ r \\] | \\. | (? : (? : \ r \ n) ? [\ t])) * "(? : (? : \ r \ n)? [\ t])
*)) * @ (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (? : (? : (? : \ r \ n)? [\ t])
+ | \ Z | (? = [\ [ "() <> @,; :: \\". \ [\]])) | \ [([^ \ [\] \ r \\] | \\. ) * \] (? : (? : \ r \ n)? [\ t]) *) (? : \
. (? : (? : \ r \ n)? [\ t]) * (? : [^ () <> @,; : \\ ". \ [\] \ 000- \ 031] + (?: (? : (? : \ r \ n)? [\ t]) + | \ Z
| (? = [\ [ "() <> @,; : \\". \ [\]])) | \ [([^ \ [\] \ r \\] | \\.) * \] (? : (? : \ r \ n)? [\ t]) *)) * \> (? :(
? : \ r \ n)? [\ t]) *)) *)?; \ s *)

26
.NET 4.0의 MailAddress 클래스는 이전 버전보다 이메일 주소를 검증하는 데 훨씬 더 좋습니다. 나는 그것에 약간의 개선을했다.
Jeff Tucker

7
간단한 ID에 대해서는 일종의 ... 작동하지 않는다고 생각합니다. a @ b는 유효성을 검사하지 않습니다. ar@b.com은 ar @ b까지만 일치하며 .com은 일치하지 않습니다. 그러나 "I am me"@ [10.10.10.10]과 같은 기능이 작동합니다! :)
Raze

5
이 RFC 호환 정규식 유효성 검사기는 "a <body / onload = alert ( ' lol.com?'+document.cookies ) @aa> 와 같이 원하지 않는 많은 전자 메일 주소를 통해 알려줍니다. "이것은 perl의 Email :: Valid (유효한 정규식을 사용함)에서 유효한 이메일 주소이며 XSS rt.cpan.org/Public/Bug/Display.html?id=75650
Matthew Lock

9
@ MatthewLock : 그보다 나쁘지 않습니다 fake@not-a-real-domain.name. 당신은 XSS를 방지하기 위해 이메일 확인에 의존하고 있습니다.
SLaks

10
@MatthewLock : 아니요 . SQL 쿼리 를 이스케이프 해야 합니다 (또는 매개 변수를 사용하는 것이 좋습니다). 살균은 적절한 방어가 아닙니다.
SLaks

536

이 질문은 많이 제기되지만 이메일 주소를 구문 적으로 검증하고 싶은 이유는 무엇입니까? 실제로 어떤 이점이 있습니까?

  • 일반적인 오타는 잡을 수 없습니다.
  • 사람들이 유효하지 않거나 구성한 전자 메일 주소를 입력하거나 다른 사람의 주소를 입력하는 것을 막지 않습니다.

전자 메일이 올바른지 확인하려면 확인 전자 메일을 보내서 사용자가 답장을 보내도록 선택할 수 있습니다. 많은 경우에 당신이 것 보안상의 이유로 윤리적 이유로 어쨌든 확인 메일을 보내 (그래서 할 수 있습니다 자신의 의지와 서비스까지하지 예를 들어, 기호 누군가).


92
그들이 단순한 실수를 잡기 위해 클라이언트 측 유효성 검사에서 필드에 뭔가를 입력했는지 확인하는 것이 가치가 있지만 일반적으로 당신은 옳습니다.
Martin Beckett

8
Martin, 나는 당신에게 +1을 주었고 나중에 foobar @ dk가 유효한 이메일이라는 것을 읽기 위해서만 예쁘지는 않지만 RFC를 준수하고 상식을 사용하려면 이와 같은 사례를 감지하고 사용자에게 올바른지 확인해야합니다.
philfreo

105
@olavk : 누군가 오타를 입력하면 (예 :) me@hotmail확인 이메일을받지 못할 것입니다. 그들은 더 이상 귀하의 사이트에 없으며 왜 그들이 가입 할 수 없는지 궁금합니다. 실제로 그들은 아닙니다. 그들은 당신에 대해 완전히 잊었습니다. 그러나 여전히 당신과 함께있는 동안 정규식으로 기본 위생 검사를 수행 할 수 있다면, 그 오류를 즉시 잡을 수 있으며 행복한 사용자가 있습니다.
nickf

5
@JacquesB : 당신은 훌륭한 지적을합니다. RFC에 따라 머 스터를 통과한다고해서 실제로 해당 사용자의 주소라는 의미는 아닙니다. 그렇지 않으면 그 모든 president@whitehouse.gov주소는 매우 netbusy 사령관을 나타냅니다. :)
tchrist

39
검은 색이나 흰색 일 필요는 없습니다. 이메일이 잘못 보이면 사용자에게 알려주십시오. 사용자가 계속 진행하고 싶다면 그에게 맡기십시오. 사용자가 정규식을 준수하도록 강요하지 말고 정규식을 도구로 사용하여 실수가있을 수 있음을 사용자에게 알리십시오.
ninjaneer

354

그것은 모두 당신이 얼마나 정확한지에 달려 있습니다. 내 목적을 위해 bob @ aol.com(이메일에 공백) 또는 steve(도메인이 전혀 없음) 또는 mary@aolcom(.com 이전에는 없음 ) 과 같은 것을 차단하려는 경우

/^\S+@\S+\.\S+$/

물론 유효하지 않은 이메일 주소와 일치하지만 일반적인 간단한 오류가 발생합니다.

해당 정규 표현식에 대해 많은 변경 사항이 있으며 일부는이 답변에 대한 의견에 있지만 간단하고 이해하기 쉽고 첫 번째 시도입니다.


6
유효하고 작동하는 이메일 주소 인 foobar @ dk와 일치하지 않습니다 (아마도 대부분의 메일 서버가이를 수락하지 않거나 something.com을 추가 할 것입니다)
bortzmeyer

3
그렇습니다. 나는 당신이 그것을 직접 시도하는 것이 좋습니다. $ perl-le'print q{foo@bar.co.uk} = ~ /^\S+@\S+\.\S+$/? q {Y} : q {N} '
Andy Lester

7
@Richard : .는에 포함되어 \S있습니다.
David Thornley

43
JJJ : 예, 많은 쓰레기와 일치합니다. & $ * # $ (@ $ 0 (%)) $ #.) & *) (* $ 와도 일치 할 것입니다. 저에게는 mary@aolcom완전한 쓰레기 인 것보다 이상한 fumble-finger 오타를 잡는 것이 더 중요합니다 YMMV.
Andy Lester

5
단지를 통제하는 @징후 : /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/ jsfiddle.net/b9chris/mXB96
크리스 Moschini

338

그것은 당신이 가장 의미하는 바에 달려 있습니다 : 유효한 모든 이메일 주소를 잡는 것에 대해 이야기하고 있다면 다음을 사용하십시오 :

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ 
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
 \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
 \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] 
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
 \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)

( http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html ) 더 간단한 것을 찾고 있지만 가장 유효한 이메일 주소를 찾으려면 다음과 같이 시도하십시오.

"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"

편집 : 링크에서 :

이 정규식은 주석이 제거되고 공백으로 대체 된 주소 만 유효성을 검사합니다 (모듈에서 수행함).


10
모든 주소와 일치하지는 않으며 일부 주소를 먼저 변환해야합니다. 링크에서 : "이 정규 표현식은 주석이 제거되고 공백으로 대체 된 주소의 유효성을 검사합니다 (모듈에서 수행함)."
Chas. Owens

47
email address두 번째 것을 잘못 통과하지만 더 긴 정규 표현식에 걸리는 일부 예를 들어 주 시겠습니까?
Lazer

4
한 번은 그것을 좋아했지만 RFC 5322가 아닌 RFC 822 유효성 검사기 입니다.
tchrist

24
@Lazer in..valid @ example.com은 간단한 예입니다. 로컬 부분에는 인용되지 않은 두 개의 연속 된 점이있을 수 없습니다.
Randal Schwartz

5
@ Mikhail perl 그러나 실제로 사용해서는 안됩니다.
Good Person

287

[업데이트 됨] 이메일 주소 확인에 대해 내가 아는 모든 것을 여기에 정리했습니다 : http://isemail.info , 이제 이메일 주소의 문제를 검증 할뿐만 아니라 진단합니다. 유효성 검사는 답변의 일부일 뿐이라는 많은 의견에 동의합니다. http://isemail.info/about 에서 내 에세이를 참조하십시오 .

is_email ()은 내가 아는 한 주어진 문자열이 유효한 이메일 주소인지 아닌지를 확실하게 알려주는 유일한 유효성 검사기입니다. http://isemail.info/ 에서 새 버전을 업로드했습니다.

Cal Henderson, Dave Child, Phil Haack, Doug Lovell, RFC5322 및 RFC 3696에서 테스트 사례를 수집했습니다. 내가 찾은 모든 무료 유효성 검사기에 대해 이러한 모든 테스트를 실행했습니다.

사람들이 유효성 검사기를 향상시킬 때이 페이지를 최신 상태로 유지하려고합니다. 이 테스트를 컴파일하고 내 검증 자의 건설적인 비판에 도움을 주신 Cal, Michael, Dave, Paul 및 Phil에게 감사의 말을 전 합니다.

사람들은 특히 RFC 3696 에 대한 정오표를 알고 있어야합니다 . 정식 예제 중 3 개는 실제로 잘못된 주소입니다. 주소의 최대 길이는 320이 아닌 254 자 또는 256 자 입니다.


이 유효성 검사기 도 올바른 것 같습니다. [... 시간이 지남 ...] 흠, 3693이나 정오표가 아니라 RFC 5322 인 것 같습니다.
tchrist

1
아주 좋아요 여기서 우리는 좋은 에세이를 얻을뿐만 아니라, 유효성 검사기 및 다운로드 할 라이브러리를 얻습니다. 좋은 대답입니다!
bgmCoder 2018

유효성 검사기는 퓨니 코드 (RFC 3492)를 지원하지 않습니다. name@öäü.at는 유효한 주소 일 수 있습니다. (name@xn--4ca9at.at로 번역됨)
Josef는 Monica Monica Reinstate Monica

안녕하세요 @Josef. name@xn--4ca9at.at이 코드는 해석이 아니라 검증에 관한 것이므로 검증을 시도해야합니다 . 퓨니 코드 번역기를 추가하고 싶다면 github.com/dominicsayers/isemail
Dominic Sayers

266

은 W3C HTML5 사양 :

^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$

문맥:

유효한 이메일 주소 생산 ABNF [...]을 일치하는 문자열이다.

참고 :이 요구 사항은 RFC 5322고의적 인 위반 으로 , 동시에 너무 엄격한 ( "@"문자 앞), 너무 모호한 ( "@"문자 뒤), 너무 느슨한 이메일 주소에 대한 구문을 정의합니다 ( 주석, 공백 문자 및 대부분의 사용자에게 친숙하지 않은 방식으로 인용 된 문자열)을 실제로 사용할 수 있습니다.

다음 JavaScript 및 Perl 호환 정규식은 위 정의를 구현 한 것입니다.

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/


12
이것은 흥미 롭다. 그것은 RFC를 위반하지만, 고의적이며 sesne을 만듭니다. 실제 예 : gmail은 @ 이전 부분의 점을 무시하므로 이메일이 test@gmail.com 인 경우 test. @ gmail.com 또는 test .... @ gmail.com으로 이메일을 보낼 수 있습니다. RFC에 따라 유효하지 않지만 실제 세계에서는 유효합니다.
valentinas

마지막 부분은 '*'대신 '+'여야한다고 생각합니다. ^ [a-zA-Z0-9.! # $ % & '* + / =? ^ _`{|} ~-] + @ [a- zA-Z0-9-] + (? : \. [a-zA-Z0-9-] +) + $
mmmmmm 2012 년

7
@mmmmmm john.doe@localhost이 유효합니다. (즉, 지역 사회)는 실제 응용 프로그램에서, 확실히, 당신은 * 대체 +에 의해하는 것이 좋습니다 싶습니다
rabudde

3
@valentinas 실제로 RFC는 이러한 로컬 부분을 배제 하지 않지만 인용해야합니다. "test...."@gmail.comRFC에 따라 완벽하게 유효하며 의미 적으로와 같습니다 test....@gmail.com.
Rinke

. @ 또는 .. @로 주소를 보내려고하면 회사 릴레이를 통해 파이썬을 사용하여 이메일을 보내려고 할 때 오류가 발생합니다. 실제로 _ @도 마찬가지입니다. 받는 사람이 할 것이라고 믿는 것보다 보내기 전에 제거합니다.
ndvo

201

Perl 5.10 이상에서는 쉽습니다.

/(?(DEFINE)
   (?<address>         (?&mailbox) | (?&group))
   (?<mailbox>         (?&name_addr) | (?&addr_spec))
   (?<name_addr>       (?&display_name)? (?&angle_addr))
   (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
   (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ;
                                          (?&CFWS)?)
   (?<display_name>    (?&phrase))
   (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

   (?<addr_spec>       (?&local_part) \@ (?&domain))
   (?<local_part>      (?&dot_atom) | (?&quoted_string))
   (?<domain>          (?&dot_atom) | (?&domain_literal))
   (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                 \] (?&CFWS)?)
   (?<dcontent>        (?&dtext) | (?&quoted_pair))
   (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

   (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
   (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
   (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
   (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

   (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
   (?<quoted_pair>     \\ (?&text))

   (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
   (?<qcontent>        (?&qtext) | (?&quoted_pair))
   (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                        (?&FWS)? (?&DQUOTE) (?&CFWS)?)

   (?<word>            (?&atom) | (?&quoted_string))
   (?<phrase>          (?&word)+)

   # Folding white space
   (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
   (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
   (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
   (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
   (?<CFWS>            (?: (?&FWS)? (?&comment))*
                       (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

   # No whitespace control
   (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

   (?<ALPHA>           [A-Za-z])
   (?<DIGIT>           [0-9])
   (?<CRLF>            \x0d \x0a)
   (?<DQUOTE>          ")
   (?<WSP>             [\x20\x09])
 )

 (?&address)/x

20
파이썬에서 이것을보고
싶습니다

4
addrspec부품 의 일부만 문제와 관련이 있다고 생각합니다 . 전체 RFC5822 주소를 수용 할 준비가되지 않은 시스템의 다른 부분은 촬영과 같지만 그 이상을 수용하고 전달하는 것은 사용자의 발입니다.
고인돌

3
훌륭하지만 (+1) 기술적으로 이것은 정규 표현식이 아닙니다 ... (문법이 규칙적이지 않기 때문에 불가능할 것입니다).
Rinke

10
정규식은 얼마 전에 규칙적으로 멈추었습니다. 그래도 유효한 Perl 'regex'입니다!
rjh

4
IDEone에서이 정규식에 대한 테스트를 설정했습니다. ideone.com/2XFecH 그러나 "완전히"공정하지 않습니다. 누구든지 차를 울려 줄까? 뭔가 빠졌습니까?
Mike

159

나는 사용한다

^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

RegularExpressionValidator가 ASP.NET에서 사용하는 것입니다.


28
우우! 본인의 (권장되지 않은) 주소 !@mydomain.net가 거부되었습니다.
Phrogz

3
이 페이지 data.iana.org/TLD/tlds-alpha-by-domain.txt 에 따르면 최상위에 한 문자 만있는 도메인이 없습니다 (예 : "something.c", "something.a"). 최소 2 개의 문자 지원 : "something.pl", "something.us":^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w{2,}([-.]\\w+)*$
Tomasz Szulc

4
@ 웨인 휘티 이메일 유효성 검사를 테스트하는 경우를 제외하고는 아무도 사용하지 않는 주소를 포함하여 대부분의 주소 또는 ALL을 제공할지 여부에 대한 주요 문제에 부딪 쳤습니다.
Patanjali

@TomaszSzulc 귀하의 답변에 여분의 백 슬래시가 혼란 스럽습니다. 방금 수정했으며 2 개의 문자 도메인 이름 지원이 작동하고 있습니다. ^ \ w + ([-+. '] \ w +) * @ \ w + ([-.] \ w +) * \. \ w {2,} ([-.] \ w +) * $
Aqib Mumtaz

2
이것은 simon-@hotmail.com실제로 유효하지 않습니다 (실제로 고객의 주소가 비슷합니다)`
Simon_Weaver

142

가장 잘 모르지만 주소에 주석이 제거되고 공백으로 대체되는 한 이것은 정확합니다.

진심으로. 이메일 유효성 검사를 위해 이미 작성된 라이브러리를 사용해야합니다. 가장 좋은 방법은 해당 주소로 확인 이메일을 보내는 것입니다.


2
내가 아는 한 일부 라이브러리도 잘못되었습니다. PHP PEAR에 이런 버그가 있다는 것을 모호하게 기억합니다.
bortzmeyer

또한이 페이지에는 사양의 몇 가지 사항에 대한 면책 ​​조항이 있습니다. 정규 표현식이 지원하지 않습니다.
Chris Vest

7
RFC 5322 사양이 아니라 RFC 822 사양입니다.
tchrist

12
궁극적으로, 그는 이메일 주소 를 실제로 확인 하는 유일한 방법 은 이메일을 보내고 답장을 기다리는 것입니다.
Blazemonger

109

유효성을 검사하려는 전자 메일 주소는 System.Net.Mail 네임 스페이스를 사용하여 ASP.NET 웹 응용 프로그램에서 사람들 목록으로 전자 메일을 보내는 데 사용됩니다. 따라서 매우 복잡한 정규식을 사용하는 대신 주소에서 MailAddress 인스턴스를 만들려고합니다. 주소가 올바르게 구성되지 않으면 MailAddress 구성자가 예외를 처리합니다. 이런 식으로, 나는 최소한 이메일을 문 밖으로 가져올 수 있다는 것을 알고 있습니다. 물론 이것은 서버 측 유효성 검사이지만 최소한 어쨌든 필요합니다.

protected void emailValidator_ServerValidate(object source, ServerValidateEventArgs args)
{
    try
    {
        var a = new MailAddress(txtEmail.Text);
    }
    catch (Exception ex)
    {
        args.IsValid = false;
        emailValidator.ErrorMessage = "email: " + ex.Message;
    }
}

3
좋은 지적입니다. 이 서버 유효성 검사에서 일부 유효한 주소를 거부하더라도이 특정 서버 기술을 사용하여이 주소로 보낼 수 없으므로 문제가되지 않습니다. 또는 기본 도구 대신 사용하는 타사 전자 메일 라이브러리를 사용하여 동일한 작업을 시도 할 수 있습니다.
사용자

나는 이것이 .Net 프레임 워크 코드를 어떻게 활용하는지 좋아합니다. 이것은 우수하다. 간단하고 깨끗하며 실제로 이메일을 보낼 수 있습니다. 훌륭한 일.
코리 하우스

... 그렇습니다. 유효성 검사 방법에 관심이있는 사람들은 Reflector의 코드를 살펴보십시오. 많은 부분이 있습니다. 정규 표현식이 아닙니다!
Tom Carter

2
참고 사항 : MailAddress 클래스는 유효성 검사에 사용하려는 경우 RFC5322와 일치하지 않습니다 (또한 전송하지 않으면 위에서 언급 한 것처럼 문제가되지 않습니다). 다음을 참조하십시오 : stackoverflow.com/questions/6023589/…
porges

사소한 문제 : 서버 측 유효성 검사기 코드를이 재사용 가능 (이 경우 또는 일반적으로)으로 재사용하려면 하드 코딩 된 args.Value필드를 참조하는 대신 사용 하는 것이 좋습니다 txtEmail.Text. 후자는 유효성 검사기를 단일 제어 인스턴스에 바인딩합니다. 단일 전자 메일 필드가있는 한 괜찮을 수도 있지만 그렇지 않은 경우에는 권장되지 않습니다.
pholpar

109

빠른 답변

입력 검증에 다음 정규식을 사용하십시오.

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+

이 정규식과 일치하는 주소 :

  • RFC 5321/5322를 엄격히 준수하는 로컬 부분 (예 : @ 기호 앞 부분)이 있어야합니다.
  • 최소한 두 개의 레이블이있는 호스트 이름 인 도메인 부분 (예 : @ 기호 뒤의 부분)이 있으며 각 레이블은 최대 63 자입니다.

두 번째 제약은 RFC 5321/5322에 대한 제한입니다.

정교한 답변

전자 메일 주소를 인식하는 정규식을 사용하면 문서에서 전자 메일 주소를 검색하거나 사용자 입력을 확인하거나 데이터 저장소의 무결성 제약 조건과 같은 다양한 상황에서 유용 할 수 있습니다.

그러나 주소가 실제로 기존 사서함을 참조하는지 확인하려면 해당 주소로 메시지를 보내는 대신 사용할 수 없습니다. 주소가 문법적으로 정확한지 확인하려면 정규식을 사용할 수 있지만 ""@[]기존 사서함을 참조하지 않는 문법적으로 정확한 전자 메일 주소입니다.

이메일 주소의 구문은 다양한 RFC , 특히 RFC 822RFC 5322 에서 정의되었습니다 . RFC 822는 "원본"표준으로, RFC 5322는 최신 표준으로 간주해야합니다. RFC 822에 정의 된 구문은 가장 관대하며 그 이후의 표준으로 인해 새로운 시스템이나 서비스가 더 이상 사용되지 않는 구문을 인식해야하지만 구문을 생성하지 않아야합니다.

이 대답에 나는 의미하는 "이메일 주소"를 할게요 addr-specRFC의 정의 (예로서 jdoe@example.org,하지만 "John Doe"<jdoe@example.org>,도 some-group:jdoe@example.org,mrx@exampel.org;).

RFC 구문을 정규식으로 변환하는 데 한 가지 문제점이 있습니다. 구문이 규칙적이지 않습니다! 무한 중첩은 정규 표현식으로 설명 할 수 없지만 무한 중첩 될 수있는 이메일 주소에 선택적 주석을 허용하기 때문입니다. 주석이 포함 된 주소를 스캔하거나 확인하려면 구문 분석기 또는보다 강력한 표현식이 필요합니다. Perl과 같은 언어에는 컨텍스트 프리 문법을 정규식과 같은 방식으로 설명하는 구문이 있습니다.이 답변에서는 주석을 무시하고 적절한 정규식 만 고려합니다.

RFC는 이메일 주소가 아닌 이메일 메시지의 구문을 정의합니다. 주소는 다양한 헤더 필드에 나타날 수 있으며 여기에서 주로 정의됩니다. 헤더 필드에 나타날 때 주소에는 어휘 토큰 사이에 공백, 주석 및 줄 바꿈이 포함될 수 있습니다. 그러나 의미 상 이것은 의미가 없습니다. 주소에서이 공백 등을 제거하면 의미 적으로 동등한 표준 표현 을 얻을 수 있습니다. 따라서의 표준 표현은 first. last (comment) @ [3.5.7.9]입니다 first.last@[3.5.7.9].

다른 목적으로 다른 구문을 사용해야합니다. 매우 오래된 문서에서 전자 메일 주소를 검색하려면 RFC 822에 정의 된 구문을 사용하는 것이 좋습니다. 반면에 사용자 입력의 유효성을 검사하려면 RFC 5322에 정의 된 구문으로, 정규 표현 만 허용합니다. 특정 사례에 적용 할 구문을 결정해야합니다.

ASCII 호환 문자 집합을 가정하여 POSIX "확장 된"정규식을이 답변에 사용합니다.

RFC 822

나는 다음 정규식에 도착했다. 나는 모든 사람들이 그것을 시도하고 깨뜨 리도록 초대합니다. 오탐 또는 오탐을 발견하면 의견에 게시하고 가능한 빨리 식을 수정하도록 노력하겠습니다.

([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*

나는 그것이 정오표를 포함하여 RFC 822를 완전히 준수한다고 생각합니다 . 표준 형식의 전자 메일 주소 만 인식합니다. 공백을 인식 (접기)하는 정규식에 대해서는 아래 파생을 참조하십시오.

파생은 내가 어떻게 표현에 도착했는지 보여줍니다. RFC의 모든 관련 문법 규칙을 표시된대로 정확하게 나열한 다음 해당 정규식을 나열합니다. 정오표가 게시 된 곳에서는 수정 된 문법 규칙 ( "erratum"으로 표시)에 대해 별도의 식을 제공하고 후속 정규식에서 업데이트 된 버전을 하위 식으로 사용합니다.

단락 3.1.4에 명시된 바와 같이. RFC 822의 선택적 선형 공백은 어휘 토큰 사이에 삽입 될 수 있습니다. 해당되는 경우이 규칙을 수용하도록 표현식을 확장하고 결과를 "opt-lwsp"로 표시했습니다.

CHAR        =  <any ASCII character>
            =~ .

CTL         =  <any ASCII control character and DEL>
            =~ [\x00-\x1F\x7F]

CR          =  <ASCII CR, carriage return>
            =~ \r

LF          =  <ASCII LF, linefeed>
            =~ \n

SPACE       =  <ASCII SP, space>
            =~  

HTAB        =  <ASCII HT, horizontal-tab>
            =~ \t

<">         =  <ASCII quote mark>
            =~ "

CRLF        =  CR LF
            =~ \r\n

LWSP-char   =  SPACE / HTAB
            =~ [ \t]

linear-white-space =  1*([CRLF] LWSP-char)
                   =~ ((\r\n)?[ \t])+

specials    =  "(" / ")" / "<" / ">" / "@" /  "," / ";" / ":" / "\" / <"> /  "." / "[" / "]"
            =~ [][()<>@,;:\\".]

quoted-pair =  "\" CHAR
            =~ \\.

qtext       =  <any CHAR excepting <">, "\" & CR, and including linear-white-space>
            =~ [^"\\\r]|((\r\n)?[ \t])+

dtext       =  <any CHAR excluding "[", "]", "\" & CR, & including linear-white-space>
            =~ [^][\\\r]|((\r\n)?[ \t])+

quoted-string  =  <"> *(qtext|quoted-pair) <">
               =~ "([^"\\\r]|((\r\n)?[ \t])|\\.)*"
(erratum)      =~ "(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"

domain-literal =  "[" *(dtext|quoted-pair) "]"
               =~ \[([^][\\\r]|((\r\n)?[ \t])|\\.)*]
(erratum)      =~ \[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]

atom        =  1*<any CHAR except specials, SPACE and CTLs>
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+

word        =  atom / quoted-string
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"

domain-ref  =  atom

sub-domain  =  domain-ref / domain-literal
            =~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]

local-part  =  word *("." word)
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*

domain      =  sub-domain *("." sub-domain)
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*

addr-spec   =  local-part "@" domain
            =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*(\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*)*@((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(canonical) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*

RFC 5322

나는 다음 정규식에 도착했다. 나는 모든 사람들이 그것을 시도하고 깨뜨 리도록 초대합니다. 오탐 또는 오탐을 발견하면 의견에 게시하고 가능한 빨리 식을 수정하도록 노력하겠습니다.

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])

나는 그것이 정오표를 포함하여 RFC 5322를 완전히 준수한다고 생각합니다 . 표준 형식의 전자 메일 주소 만 인식합니다. 공백을 인식 (접기)하는 정규식에 대해서는 아래 파생을 참조하십시오.

파생은 내가 어떻게 표현에 도착했는지 보여줍니다. RFC의 모든 관련 문법 규칙을 표시된대로 정확하게 나열한 다음 해당 정규식을 나열합니다. 의미 상 관련이없는 (접기) 공백을 포함하는 규칙의 경우이 공백을 허용하지 않는 "(정규화 된)"으로 표시된 별도의 정규식을 제공합니다.

RFC의 모든 "obs-"규칙을 무시했습니다. 이는 정규 표현식이 RFC 5322를 엄격하게 준수하는 이메일 주소와 만 일치 함을 의미합니다. "오래된"주소와 일치해야하는 경우 ( "obs-"규칙을 포함한 느슨한 문법처럼) 이전 단락의 RFC 822 정규식 중 하나를 사용할 수 있습니다.

VCHAR           =   %x21-7E
                =~  [!-~]

ALPHA           =   %x41-5A / %x61-7A
                =~  [A-Za-z]

DIGIT           =   %x30-39
                =~  [0-9]

HTAB            =   %x09
                =~  \t

CR              =   %x0D
                =~  \r

LF              =   %x0A
                =~  \n

SP              =   %x20
                =~  

DQUOTE          =   %x22
                =~  "

CRLF            =   CR LF
                =~  \r\n

WSP             =   SP / HTAB
                =~  [\t ]

quoted-pair     =   "\" (VCHAR / WSP)
                =~  \\[\t -~]

FWS             =   ([*WSP CRLF] 1*WSP)
                =~  ([\t ]*\r\n)?[\t ]+

ctext           =   %d33-39 / %d42-91 / %d93-126
                =~  []!-'*-[^-~]

("comment" is left out in the regex)
ccontent        =   ctext / quoted-pair / comment
                =~  []!-'*-[^-~]|(\\[\t -~])

(not regular)
comment         =   "(" *([FWS] ccontent) [FWS] ")"

(is equivalent to FWS when leaving out comments)
CFWS            =   (1*([FWS] comment) [FWS]) / FWS
                =~  ([\t ]*\r\n)?[\t ]+

atext           =   ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
                =~  [-!#-'*+/-9=?A-Z^-~]

dot-atom-text   =   1*atext *("." 1*atext)
                =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*

dot-atom        =   [CFWS] dot-atom-text [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*

qtext           =   %d33 / %d35-91 / %d93-126
                =~  []!#-[^-~]

qcontent        =   qtext / quoted-pair
                =~  []!#-[^-~]|(\\[\t -~])

(erratum)
quoted-string   =   [CFWS] DQUOTE ((1*([FWS] qcontent) [FWS]) / FWS) DQUOTE [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  "([]!#-[^-~ \t]|(\\[\t -~]))+"

dtext           =   %d33-90 / %d94-126
                =~  [!-Z^-~]

domain-literal  =   [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
                =~  (([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  \[[\t -Z^-~]*]

local-part      =   dot-atom / quoted-string
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+"

domain          =   dot-atom / domain-literal
                =~  (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized)    =~  [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*]

addr-spec       =   local-part "@" domain
                =~  ((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?)@((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?)
(normalized)    =~  ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])

일부 소스 (특히 w3c )는 RFC 5322가 로컬 부분 (즉, @ 기호 앞 부분)에서 너무 엄격하다고 주장합니다. "..", "a..b"및 "a."때문입니다. 사서함 이름으로 사용될 수 있지만 유효한 점 원자 는 아닙니다 . 은 RFC 그러나 않습니다 그들이 인용하는 경우를 제외 해,이 같은 지역 부품 수 있습니다. 따라서 대신에 의미 론적으로 동등한을 a..b@example.net작성해야합니다 "a..b"@example.net.

추가 제한 사항

SMTP ( RFC 5321에 정의 된 대로 )는 유효한 이메일 주소 세트 (또는 실제로는 사서함 이름)를 제한합니다. 이 엄격한 문법을 ​​적용하는 것이 합리적이므로 일치하는 전자 메일 주소를 실제로 전자 메일을 보내는 데 사용할 수 있습니다.

RFC 5321은 기본적으로 "로컬"부분 (예 : @ 기호 앞 부분) 만 남겨두고 도메인 부분 (예 : @ 기호 뒤에있는 부분)에서 더 엄격합니다. 도트 원자 대신 호스트 이름 만 허용하고 도메인 리터럴 대신 주소 리터럴을 허용합니다.

RFC 5321에 제시된 문법은 호스트 이름과 IP 주소 모두에있어 너무 관대합니다. 이 초안RFC 1034 를 지침으로 사용하여 문제의 규칙을 "수정"할 자유를 얻었습니다 . 결과 정규식은 다음과 같습니다.

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])

유스 케이스에 따라 정규 표현식에서 "일반 주소 리터럴"을 허용하지 않을 수도 있습니다. 또한 (?!IPv6:)"General-address-literal"부분이 잘못된 IPv6 주소와 일치하지 않도록하기 위해 최종 정규식에서 부정적 예측 을 사용했습니다 . 일부 정규식 프로세서는 부정적 예측을 지원하지 않습니다. |(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+전체 "일반 주소-리터럴"부분을 꺼내려면 정규식 에서 하위 문자열 을 제거하십시오 .

파생은 다음과 같습니다.

Let-dig         =   ALPHA / DIGIT
                =~  [0-9A-Za-z]

Ldh-str         =   *( ALPHA / DIGIT / "-" ) Let-dig
                =~  [0-9A-Za-z-]*[0-9A-Za-z]

(regex is updated to make sure sub-domains are max. 63 charactes long - RFC 1034 section 3.5)
sub-domain      =   Let-dig [Ldh-str]
                =~  [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?

Domain          =   sub-domain *("." sub-domain)
                =~  [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*

Snum            =   1*3DIGIT
                =~  [0-9]{1,3}

(suggested replacement for "Snum")
ip4-octet       =   DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35
                =~  25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]

IPv4-address-literal    =   Snum 3("."  Snum)
                        =~  [0-9]{1,3}(\.[0-9]{1,3}){3}

(suggested replacement for "IPv4-address-literal")
ip4-address     =   ip4-octet 3("." ip4-octet)
                =~  (25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}

(suggested replacement for "IPv6-hex")
ip6-h16         =   "0" / ( (%x49-57 / %x65-70 /%x97-102) 0*3(%x48-57 / %x65-70 /%x97-102) )
                =~  0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}

(not from RFC)
ls32            =   ip6-h16 ":" ip6-h16 / ip4-address
                =~  (0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}

(suggested replacement of "IPv6-addr")
ip6-address     =                                      6(ip6-h16 ":") ls32
                    /                             "::" 5(ip6-h16 ":") ls32
                    / [                 ip6-h16 ] "::" 4(ip6-h16 ":") ls32
                    / [ *1(ip6-h16 ":") ip6-h16 ] "::" 3(ip6-h16 ":") ls32
                    / [ *2(ip6-h16 ":") ip6-h16 ] "::" 2(ip6-h16 ":") ls32
                    / [ *3(ip6-h16 ":") ip6-h16 ] "::"   ip6-h16 ":"  ls32
                    / [ *4(ip6-h16 ":") ip6-h16 ] "::"                ls32
                    / [ *5(ip6-h16 ":") ip6-h16 ] "::"   ip6-h16
                    / [ *6(ip6-h16 ":") ip6-h16 ] "::"
                =~  (((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::

IPv6-address-literal    =   "IPv6:" ip6-address
                        =~  IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)

Standardized-tag        =   Ldh-str
                        =~  [0-9A-Za-z-]*[0-9A-Za-z]

dcontent        =   %d33-90 / %d94-126
                =~  [!-Z^-~]

General-address-literal =   Standardized-tag ":" 1*dcontent
                        =~  [0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+

address-literal =   "[" ( IPv4-address-literal / IPv6-address-literal / General-address-literal ) "]"
                =~  \[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)]

Mailbox         =   Local-part "@" ( Domain / address-literal )
                =~  ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])

사용자 입력 검증

일반적인 사용 사례는 사용자 입력 유효성 검사입니다 (예 : html 양식). 이 경우 일반적으로 주소 리터럴을 배제하고 호스트 이름에 두 개 이상의 레이블을 요구하는 것이 합리적입니다. 이전 섹션에서 개선 된 RFC 5321 정규식을 기본으로 사용하면 결과는 다음과 같습니다.

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+

예를 들어 따옴표로 묶은 문자열을 제외하여 로컬 부분을 더 제한하지 않는 것이 좋습니다. 일부 호스트가 어떤 종류의 사서함 이름 (예 : "a..b"@example.net또는 "a b"@example.net)을 허용하는지 알 수 없기 때문 입니다.

또한 리터럴 최상위 도메인 목록에 대해 명시 적으로 유효성 검사를하거나 길이 제약 조건을 적용하는 것도 권장하지 않습니다 ( ".museum"이 무효화 된 방법 기억 [a-z]{2,4}).

([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?\.)*(net|org|com|info|기타...)

명시적인 최상위 도메인 유효성 검사 경로를 내려 가기로 결정한 경우 정규식을 최신 상태로 유지하십시오.

추가 고려 사항

@ 기호 뒤의 도메인 부분에서 호스트 이름 만 허용하는 경우 위의 정규 표현식은 최대 63 자의 레이블 만 허용합니다. 그러나 전체 호스트 이름이 최대 253 자 (점 포함) 여야한다는 사실을 강요하지 않습니다. 이 제약 조건은 여전히 ​​규칙적으로 말하지만이 규칙을 포함하는 정규식을 만드는 것은 불가능합니다.

특히 입력 유효성 검증을 위해 정규식을 사용할 때 고려해야 할 또 다른 사항은 사용자에게 피드백입니다. 사용자가 잘못된 주소를 입력하면 간단한 "구문 적으로 잘못된 주소"보다 약간 더 많은 피드백을 제공하는 것이 좋습니다. "vanilla"정규식으로는 불가능합니다.

이 두 가지 고려 사항은 주소를 구문 분석하여 해결할 수 있습니다. 호스트 이름에 대한 추가 길이 제한은 경우에 따라이를 확인하는 추가 정규식을 사용하고 주소를 두 표현식과 일치 시켜서 해결할 수도 있습니다.

이 답변의 정규식 중 어느 것도 성능에 최적화되어 있지 않습니다. 성능이 문제인 경우 선택한 정규식을 최적화 할 수 있는지 (및 방법) 확인해야합니다.


3
완전하고 깨끗한 UTF-8을 허용하고 포함하도록 RFC 6532 업데이트 5322 가 있습니다. 자세한 내용은 여기를 참조 하십시오 .

Wikipedia에 따르면 점으로 구분 된 로컬 부분은 파트 당 64 자로 제한되며 RFC 5322는 도메인의 제한으로 해석되는 점으로 구분 된 로컬 부분을 나타냅니다. 예를 들어 arbitrary-long-email-address-should-be-invalid-arbitrary-long-email-address-should-be-invalid.and-the-second-group-also-should-not-be-so-long-and-the-second-group-also-should-not-be-so-long@example.com유효성을 검사해서는 안됩니다. 나는에 (이름 선택 점 전)과 두 번째 그룹 (다음과 같은 점 후 이름) 첫 번째 그룹에있는 "+"표시를 변경 제안{1,64}
사비 몬테로

주석의 크기가 제한되어 있으므로 여기에 사용할 계획 정규 표현식이 있습니다.이 답변의 시작 부분에 로컬 표현식의 크기를 제한하고 "/"앞에 백 슬래시를 추가하십시오. 기호 PHP로도 regex101.com에서 요구 :에서 PHP I 사용 :$emailRegex = '/^([-!#-\'*+\/-9=?A-Z^-~]{1,64}(\.[-!#-\'*+\/-9=?A-Z^-~]{1,64})*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+$/';
사비 몬테로

주의 : 어떤 이유로 StackOverflow는 렌더링 된 마크 다운에서 복사 할 때 숨겨진 문자를 추가합니다. 이것을 regex101.com에 복사하면 검은 점이 나타납니다. 당신은 그것들을 제거하고 문자열을 수정해야합니다 ... 아마도 대답에 통합되면 올바르게 복사 할 수 있습니다. 불편을 드려 죄송합니다. 이것이 올바른 답변이므로 새 답변을 추가하고 싶지 않습니다. 또한 커뮤니티에서 통합해야한다고 생각하지 않는 한 직접 편집하고 싶지 않습니다.
Xavi Montero

@Xavi에 기여해 주신 @XaviMontero Thaks! 로컬 부품 레이블의 64 자 제한을 나타내는 RFC에 대한 참조가 있습니까? 그렇다면 기꺼이 답변을 조정하겠습니다.
Rinke

73

그물에 이것의 많은 예가 있습니다 (그리고 RFC를 완전히 검증하는 것조차 생각합니다-그러나 메모리가 제공된다면 수십 / 수백 줄입니다). 사람들은 이런 종류의 일을 확인하는 경향이 있습니다. 왜 @ 하나 이상이 있는지 확인하지 않는 것이 좋습니다. 간단한 최소 길이를 충족시킵니다. 가짜 이메일을 입력하고 여전히 유효한 정규식과 일치하는 것은 쉽지 않습니다. 나는 거짓 긍정이 거짓 부정보다 낫다고 생각합니다.


1
예, 그러나 어느 RFC입니까? :)이 [RFC‐5322–validator] ( stackoverflow.com/questions/201323/… )는 40 줄 정도입니다.
tchrist

14
ㅏ . 필요하지 않습니다. TLD는 이메일 주소를 가지거나 IPv6 주소를 가질 수 있습니다
Sijmen Mulder

1
RFC는 이야기의 끝이 아닙니다 : ICANN은 더 이상 ' dotless
Synchro

64

허용되는 문자를 결정할 때는 아포스트로피와 하이픈을 넣은 친구를 기억하십시오. 회사가 HR 시스템에서 내 이름을 사용하여 내 이메일 주소를 생성한다는 사실을 통제 할 수 없습니다. 내성에 아포스트로피가 포함되어 있습니다. 내 이메일 주소가 "유효하지 않다"는 사실로 웹 사이트와의 상호 작용이 차단 된 횟수를 알려 드릴 수 없습니다.


4
이것은 사람의 이름으로 무엇이 허용되지 않는지에 대해 부주의하게 가정하는 프로그램에서 매우 일반적인 문제입니다. 그러한 가정을해서는 안되며, 관련 RFC (들)가 반드시 말해야하는 특성을 받아 들여야합니다.
tchrist

4
예. 전자 메일 주소에서 대문자를 거부하는 프로그래머에 대해 특히 분노합니다! 바보 및 / 또는 게으른.
PhiLho

63

이 정규식은 Perl의 Email :: Valid 라이브러리에 있습니다. 나는 그것이 가장 정확하다고 생각합니다. 그것은 822 개 모두와 일치합니다. 그리고 그것은 O'Reilly 책의 정규식을 기반으로합니다.

정규식 마스터 링 ( http://www.ora.com/catalog/regexp/ ) 에서 Jeffrey Friedl의 예제를 사용하여 작성된 정규식 .

$RFC822PAT = <<'EOF';
[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\
xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xf
f\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\x
ff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015
"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\
xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80
-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*
)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\
\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\
x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x8
0-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n
\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([
^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\
\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\
x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-
\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()
]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\
x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\04
0\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\
n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\
015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?!
[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\
]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\
x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\01
5()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".
\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]
)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^
()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\0
15()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][
^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\
n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\
x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?
:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-
\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*
(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015
()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()
]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\0
40)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\
[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\
xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*
)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80
-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x
80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t
]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\
\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])
*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x
80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80
-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015(
)]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\
\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t
]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\0
15()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015
()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(
\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|
\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80
-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()
]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x
80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^
\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040
\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".
\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff
])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\
\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x
80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015
()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\
\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^
(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-
\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\
n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|
\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))
[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff
\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\x
ff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(
?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\
000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\
xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\x
ff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)
*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\x
ff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-
\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)
*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\
]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\]
)[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-
\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\x
ff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(
?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80
-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<
>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x8
0-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:
\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]
*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)
*\)[\040\t]*)*)*>)
EOF

14
O_O 당신은 또한 그것이 무엇을하고 있는지 이해하기 위해 정규식 마스터가되어야합니다
Chris McGrath

45

PHP로 작성하는 동안 이메일에 PHP 내장 유효성 검사를 사용하는 것이 좋습니다.

filter_var($value, FILTER_VALIDATE_EMAIL)

5.3.6보다 낮은 php 버전을 실행하는 경우이 문제에 유의하십시오 : https://bugs.php.net/bug.php?id=53091

이 buid-in 유효성 검사 작동 방식에 대한 자세한 내용은 다음을 참조하십시오. PHP의 filter_var FILTER_VALIDATE_EMAIL이 실제로 작동합니까?


내가 말하려고했던대로 투표를합니다. IDN을 처리하지 않지만 미리 puny 코드로 변환하면이 문제가 해결됩니다. PHP> = 5.3에는 idn_to_ascii ()가 있습니다. 이메일을 확인하는 가장 쉽고 쉬운 방법 중 하나입니다.
Taylor


42

다른 사람이 이미 더 나은 버전을 만들었을 가능성이 있기 때문에 나는 내 자신의 정규 표현식으로 작성하는 것을 귀찮게하지 않습니다. 나는 항상 regexlib 를 사용하여 원하는 것을 찾습니다.


1
이것은 길이와 내용으로 플래그가 지정되었지만 여전히 41 표로 좋은 공헌을하고 있으며 삭제해서는 안됩니다.

37

실제로 사용할 수있는 것은 없습니다.
내에서 몇 가지 문제 논의 거기에 이메일 주소 확인을위한 PHP 라이브러리를 대답을? 전자 메일 주소의 정규식 인식에 대해서도 논의되어 있습니까?

간단히 말해서, 사용 가능한 단일 정규 표현식이 올바른 작업을 수행 할 것으로 기대하지 마십시오. 그리고 최고의 정규 표현식은 전자 메일의 유효성이 아닌 구문의 유효성을 검사합니다 (jhohn@example.com은 정확하지만 반송 될 것입니다 ...).


내가 틀렸다면 수정하지만 PHP는 PCRE 패턴을 사용한다고 생각합니다. 그렇다면 Abigail의 RFC 5322 패턴 과 비슷한 것을 만들 수 있어야합니다 .
tchrist

@ tchrist : PCRE 가이 구문 (내가 발견 한)을 따라 잡았는지 확실하지 않습니다. 그렇다면, PHP의 PCRE가이 버전의 PCRE를 따라 잡았는지 확신 할 수 없습니다 ... 글쎄,이 구문을 올바르게 이해한다면, 정규식보다 훨씬 명확하고 완전한 PEG 파서를 사용할 수 있습니다.
PhiLho

PCRE가이 따라 잡았지만 PHP는 PCRE를 따라 잡지 않았을 것입니다. ☹
tchrist

36

유효한 전자 메일 주소를 적어도 거부하지 않는 간단한 정규 표현식은 무언가를 확인한 다음 @ 기호를 사용한 다음 마침표와 적어도 2 개의 무언가를 확인하는 것입니다. 아무것도 거부하지 않지만 사양을 검토 한 후 유효하고 거부되는 이메일을 찾을 수 없습니다.

이메일 = ~ /.+@[^@]+\.[^@]{2,}$/


3
이것이 내가 찾던 것입니다. 매우 제한적이지는 않지만 1 @ 만 있어야합니다 (목록을 구문 분석하고 누락 된 쉼표가 없는지 확인하려는 경우). 참고로, Valid_email_addresses라는 인용 부호가 있으면 왼쪽에 @을 사용할 수 있지만 꽤 프린지입니다.
Josh

2
그것을 사용한 후에는 정확히 작동하지 않는다는 것을 깨달았습니다. /^[^@]+@[^@]+\.[^@]{2}[^@]*$/ 실제로 1 @ 부호를 확인합니다. 정규 표현식은 끝에. * 때문에 여러 번 통과시킵니다.
Josh

1
권리. 유효하지 않은 모든 이메일을 거부하지 않고 유효한 이메일 주소를 거부하지 마십시오.
spig

1
이것을 사용하는 것이 훨씬 낫습니다 : /^[^@]+@[^@]+\.[^@]{2,4}$/@가 아닌 2 ~ 4 문자로 끝나야합니다. @Josh가 지적했듯이 이제 끝에 추가 @를 허용합니다. 그러나 /^[^@]+@[^@]+\.[^a-z-A-Z]{2,4}$/모든 최상위 도메인은 aZ 문자이므로 이를 변경할 수도 있습니다 . 당신은 대체 할 수 45이상 최상위 도메인 이름이 미래에 더 이상있을 수뿐만 아니라.
FLY

@FLY, ka @ foo. 올바른 것을 반환합니다. 표준에 따라야합니까?
SexyBeast

29

jQuery Validation 플러그인에서 사용하는 것을 사용할 수 있습니다.

/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i

이것은 좋은 일을하는 것 같습니다. 그것은 허용 : a-b'c_d.e@f-g.h하지만 같은 부적절한 변화를 잡을 수 있었다 a-b'c_d.@f-g.ha-b'c_d.e@f-.h
dsdsdsdsd

25

이메일 주소 확인을위한 최상의 정규식에 대한 가장 포괄적 인 평가는이 링크를 참조하십시오. " 정규식을 검증하는 이메일 주소 비교 "

다음은 참조 용으로 현재 최상위 표현식입니다.

/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i

spoon16 : 그 링크는 실제로 정확하지 않습니다. 이메일 주소를 검증하기위한 완벽한 패턴이 없을 수 있다는 주장은 특허 적으로 결함입니다. 당신 은 할 수 있지만 RFC를 따라 편지를 따라야합니다. 또한 올바른 RFC를 선택해야합니다.
tchrist

문자열을 올바르게 이스케이프하고 변환 한 후에도 "best"는 Java 정규식과 함께 작동하지 않습니다.
Eric Chen

23

비 라틴어 (중국어, 아랍어, 그리스어, 히브리어, 키릴 어 등) 도메인 이름은 가까운 시일 내에 허용됩니다 . 이 문자들은 반드시 [a-z]/inor 로 덮여 있지 않기 때문에 모든 사람이 사용하는 이메일 정규식을 변경해야합니다 \w. 그들은 모두 실패합니다.

결국, 전자 메일 주소를 확인 하는 가장 좋은 방법은 실제로 해당 주소로 전자 메일을 보내 주소를 확인하는 것입니다. 이메일 주소가 사용자 인증 (등록 / 로그인 등)의 일부인 경우 사용자 활성화 시스템과 완벽하게 결합 할 수 있습니다. 즉, 고유 한 활성화 키가있는 링크가 포함 된 이메일을 지정된 이메일 주소로 보내고 사용자가 이메일의 링크를 사용하여 새로 만든 계정을 활성화 한 경우에만 로그인을 허용합니다.

정규식의 목적이 UI에서 지정된 이메일 주소가 올바른 형식으로 보이지 않음을 사용자에게 신속하게 알리는 것이라면 기본적으로 다음 정규식과 일치하는지 확인하는 것이 가장 좋습니다.

^([^.@]+)(\.[^.@]+)*@([^.@]+\.)+([^.@]+)$

그렇게 간단합니다. 왜 지구상에서 이름과 도메인에 사용 된 캐릭터에 관심이 있습니까? 서버가 아닌 유효한 이메일 주소를 입력하는 것은 고객의 책임입니다. 클라이언트가 와 같은 구문 상 유효한 이메일 주소를 입력하더라도 이것이 올바른 이메일 주소 aa@bb.cc임을 보장하지는 않습니다. 아무도 정규식으로 그것을 감당할 수 없습니다.


4
나는 인증 메시지를 보내는 것이 일반적으로 이런 종류의 물건에 가장 적합한 방법이라는 데 동의합니다. 내가 입력 한 내용을 볼 수없는 것처럼 "확인"에 내 이메일 주소를 두 번 입력하면 좌절됩니다. 어쨌든 첫 번째 것을 두 번째로만 복사하면 점점 더 많이 사용되는 것 같습니다.
PeteT

동의하다! 그러나이 정규 표현식 spaces@.예를 들어 허용하기 때문에 유효하지 않다고 생각합니다 . test@test.ca com net위의 정규식을 사용하여 유효하지 않은 것으로 반환되는 유효한 이메일로 간주됩니다.
CB4

20

HTML5 스펙은 제안 이메일 주소를 검증하기위한 간단한 정규식 :

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

이것은 의도적으로 RFC 5322를 준수하지 않습니다 .

참고 : 이 요구 사항은 RFC 5322고의적 인 위반 으로 , 동시에 너무 엄격한 ( 문자 앞 ), 너무 모호한 ( 문자 뒤에 ), 너무 느슨한 (주석, 공백 문자 허용) 이메일 주소에 대한 구문을 정의합니다 . 대부분의 사용자에게 익숙하지 않은 방식으로 인용 된 문자열)을 실제로 사용하십시오.@@

RFC 3696 에라타 1690에 따라 총 길이도 254 자로 제한 될 수 있습니다 .


최고의 답변! 다음은 w3 권장 사항에 대한 링크입니다. w3.org/TR/html5/forms.html#valid-e-mail-address 이 정규식은 많은 브라우저에서 채택되었습니다.
라이언 테일러

3
이것은 최고의 답변이 아닙니다! 이 패턴은 전적으로 잘못된 주소와 일치합니다 invalid@emailaddress. 나는 당신이 그것을 사용하기 전에주의와 많은 테스트를 촉구합니다!
Sheridan

@Sheridan, HTML5 사양에 문제가 있다고 생각되면 여기에서 문제를 제기 할 수 있습니다. github.com/w3c/html/issues
Luna

이것은 stackoverflow.com/a/8829363을 크게 추가하지 않으며 IMHO가 그것에 대한 편집 또는 의견으로 더 좋을 것입니다.

example @ localhost는 유효하지만 실제 응용 프로그램의 경우 도메인 확장을 시행하고 싶을 때 최종 *를 +로 변경하면됩니다 (패턴의 해당 부분을 0+에서 1+로 변경). )
Mitch Satchwell

15

생생한 시연을 위해 다음 몬스터는 훌륭하지만 구문 상 유효한 모든 이메일 주소를 올바르게 인식하지 못합니다. 중첩 된 주석은 최대 4 단계까지 인식합니다.

이것은 파서의 작업이지만 주소가 구문 적으로 유효한 경우에도 여전히 전달할 수 없습니다. 때때로 당신은 "이봐 요, ee-us!"

// derivative of work with the following copyright and license:
// Copyright (c) 2004 Casey West.  All rights reserved.
// This module is free software; you can redistribute it and/or
// modify it under the same terms as Perl itself.

// see http://search.cpan.org/~cwest/Email-Address-1.80/

private static string gibberish = @"
(?-xism:(?:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+
|\s+)*[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+(?-xism:(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+
|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(
?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?
:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x
0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*<DQ>(?-xism:(?-xism:[
^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D])))+<DQ>(?-xism:(?-xi
sm:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xis
m:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\
]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\
s*)+|\s+)*))+)?(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?
-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:
\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[
^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*<(?-xism:(?-xi
sm:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^(
)\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(
?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))
|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<
>\[\]:;@\,.<DQ>\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]
+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))
|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:
(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s
*\)\s*))+)*\s*\)\s*)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?
:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x
0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xi
sm:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*
<DQ>(?-xism:(?-xism:[^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D]
)))+<DQ>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\
]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-x
ism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+
)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))\@(?-xism:(?-xism:(?-xism:(
?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?
-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^
()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s
*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+(
?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+)*)(?-xism:(?-xism:
\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[
^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+)
)|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)
+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:
(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((
?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\
x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*\[(?:\s*(?-xism:(?-x
ism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D])))+)*\s*\](?-xi
sm:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:
\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(
?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+
)*\s*\)\s*)+|\s+)*)))>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-
xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\
s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^
\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))|(?-xism:(?-x
ism:(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^
()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*
(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D])
)|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()
<>\[\]:;@\,.<DQ>\s]+(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s
]+)*)(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+)
)|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism
:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\
s*\)\s*))+)*\s*\)\s*)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((
?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\
x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-x
ism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)
*<DQ>(?-xism:(?-xism:[^\\<DQ>])|(?-xism:\\(?-xism:[^\x0A\x0D
])))+<DQ>(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\
\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-
xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)
+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*))\@(?-xism:(?-xism:(?-xism:
(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(
?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[
^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\
s*\)\s*)+|\s+)*(?-xism:[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+
(?:\.[^\x00-\x1F\x7F()<>\[\]:;@\,.<DQ>\s]+)*)(?-xism:(?-xism
:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:
[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+
))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*
)+|\s+)*)|(?-xism:(?-xism:(?-xism:\s*\((?:\s*(?-xism:(?-xism
:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\(
(?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A
\x0D]))|)+)*\s*\)\s*))+)*\s*\)\s*)+|\s+)*\[(?:\s*(?-xism:(?-
xism:[^\[\]\\])|(?-xism:\\(?-xism:[^\x0A\x0D])))+)*\s*\](?-x
ism:(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism
:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:\s*(?-xism:(?-xism:
(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|)+)*\s*\)\s*))
+)*\s*\)\s*)+|\s+)*))))(?-xism:\s*\((?:\s*(?-xism:(?-xism:(?
>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0D]))|(?-xism:\s*\((?:
\s*(?-xism:(?-xism:(?>[^()\\]+))|(?-xism:\\(?-xism:[^\x0A\x0
D]))|)+)*\s*\)\s*))+)*\s*\)\s*)*)"
  .Replace("<DQ>", "\"")
  .Replace("\t", "")
  .Replace(" ", "")
  .Replace("\r", "")
  .Replace("\n", "");

private static Regex mailbox =
  new Regex(gibberish, RegexOptions.ExplicitCapture); 

12

공식 표준 RFC 2822 유효한 이메일 정규식 에 따르면

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Java에서 사용하려면 정말 쉽습니다.

import java.util.regex.*;

class regexSample 
{
   public static void main(String args[]) 
   {
      //Input the string for validation
      String email = "xyz@hotmail.com";

      //Set the email pattern string
      Pattern p = Pattern.compile(" (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"
              +"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")"
                     + "@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\]");

      //Match the given string with the pattern
      Matcher m = p.matcher(email);

      //check whether match is found 
      boolean matchFound = m.matches();

      if (matchFound)
        System.out.println("Valid Email Id.");
      else
        System.out.println("Invalid Email Id.");
   }
}

1
정규식에는 대문자가 포함되어 있지 않습니다 (예 : Leonardo.davinci@gmail.com) . 일부 사용자에게는 성 가실 수 있습니다. 대신 이것을 사용하십시오 :(?:[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
Kebab Krabby

@KebabKrabby 감사합니다. 답변을 수정하십시오. 변경 사항을 수락하겠습니다.
AZ_

그 변경 사항을 귀하의 답변에 추가하면 더 이상 RFC 2822가 아니므로 올바른지 모르겠습니다.
케밥 크라비

11

내가 사용하는 PHP는 다음과 같습니다. 나는 다른 주석 작성자가 선언 한 것처럼 "거짓 긍정이 거짓 긍정보다 낫다"라는 정신 으로이 솔루션을 선택했으며 응답 시간을 늘리고 서버로드를 유지하는 것과 관련하여 서버 리소스를 낭비 할 필요가 없습니다. 이것이 가장 간단한 사용자 오류를 제거 할 때 정규 표현식. 원하는 경우 언제든지 테스트 이메일을 보내서이를 확인할 수 있습니다.

function validateEmail($email) {
  return (bool) stripos($email,'@');
}

1
a) "폐기물 서버 자원"은 무한하지만 JS를 사용하여 클라이언트 측에서 할 수 있습니다. b) 등록 메일을 보내려면 무엇이 필요하고 사용자는 me @ forgotthedotcom을 입력합니까? "솔루션"이 실패하고 사용자를 잃게됩니다.
johnjohn

a) JavaScript가 비활성화되었을 때 실패 할 JS 유효성 검사에 의존하는 것이 가장 좋은 아이디어처럼 들리지 않습니다 (btw 만)
auco

11

RFC 5322 표준 :

dot-atom local-part, quoted-string local-part, 쓸모없는 (dot-atom 및 인용 문자열 혼합) local-part, 도메인 이름 도메인 (IPv4, IPv6 및 IPv4 매핑 된 IPv6 주소) 도메인 리터럴 도메인을 허용합니다. 그리고 (중첩 된) CFWS.

'/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD'

RFC 5321 표준 :

도트 원자 로컬 부분, 따옴표로 묶은 문자열 로컬 부분, 도메인 이름 도메인 및 (IPv4, IPv6 및 IPv4 매핑 IPv6 주소) 도메인 리터럴 도메인을 허용합니다.

'/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!"?(?>\\\[ -~]|[^"]){65,}"?@)(?>([!#-\'*+\/-9=?^-~-]+)(?>\.(?1))*|"(?>[ !#-\[\]-~]|\\\[ -~])*")@(?!.*[^.]{64,})(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?2)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?3)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?3)(?>:(?3)){0,6})?::(?4)?))|(?>(?>IPv6:(?>(?3)(?>:(?3)){5}:|(?!(?:.*[a-f0-9]:){6,})(?5)?::(?>((?3)(?>:(?3)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?6)){3}))\])$/iD'

기본:

도트 원자 로컬 부분 및 도메인 이름 도메인을 허용합니다 (TLD가 2-6 자의 알파벳 문자로 제한된 도메인 이름 레이블을 두 개 이상 필요).

"/^(?!.{255,})(?!.{65,}@)([!#-'*+\/-9=?^-~-]+)(?>\.(?1))*@(?!.*[^.]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?\.){1,126}[a-z]{2,6}$/iD"

악마의 언어는 무엇입니까? 나는 /D깃발을 보았고 작은 따옴표로 인용했지만 슬래시를 사용하여 패턴을 구분 했습니까? Perl이 아니며 PCRE 일 수 없습니다. 그러므로 PHP입니까? 나는 이것들이 재귀를 허용하는 유일한 세 가지라고 생각합니다 (?1).
tchrist

PCRE를 사용하는 PHP입니다. 슬래시는 괄호, 대괄호, 물론 슬래시 및 작은 따옴표와 같은 특수 문자를 구분하는 데만 사용됩니다. / D 플래그는 모르는 경우 문자열 끝에 줄 바꿈이 추가되지 않도록하는 것입니다. 그렇지 않으면 허용됩니다.
MichaelRushton

9

4 문자 TLD를 "수용 할 수 없습니다". .info.name 에서는 사람들을 금지 하고 길이 제한은 .travel.museum을 중지 하지만 그렇습니다. 2 자 TLD 및 3 자 TLD보다 덜 일반적입니다.

대문자 알파벳도 허용해야합니다. 이메일 시스템은 로컬 부분과 도메인 부분을 정규화합니다.

정규식 도메인 부분의 경우 도메인 이름은 '-'로 시작할 수 없으며 '-'로 끝날 수 없습니다. 대시는 사이에만있을 수 있습니다.

PEAR 라이브러리를 사용한 경우 메일 기능을 확인하십시오 (정확한 이름 / 라이브러리를 잊어 버렸습니다). 하나의 함수를 호출하여 이메일 주소를 검증 할 수 있으며 RFC822의 정의에 따라 이메일 주소를 검증합니다.


2
@Joseph Yee : RFC 822가 약간 날짜가 맞지 않습니까?
tchrist

8
public bool ValidateEmail(string sEmail)
{
    if (sEmail == null)
    {
        return false;
    }

    int nFirstAT = sEmail.IndexOf('@');
    int nLastAT = sEmail.LastIndexOf('@');

    if ((nFirstAT > 0) && (nLastAT == nFirstAT) && (nFirstAT < (sEmail.Length - 1)))
    {
        return (Regex.IsMatch(sEmail, @"^[a-z|0-9|A-Z]*([_][a-z|0-9|A-Z]+)*([.][a-z|0-9|A-Z]+)*([.][a-z|0-9|A-Z]+)*(([_][a-z|0-9|A-Z]+)*)?@[a-z][a-z|0-9|A-Z]*\.([a-z][a-z|0-9|A-Z]*(\.[a-z][a-z|0-9|A-Z]*)?)$"));
    }
    else
    {
        return false;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.