Лучшее регулярное выражение для проверки формата электронной почты с проверкой ASP.NET 3.5 - PullRequest
7 голосов
/ 02 июня 2009

Я использовал оба следующих регулярных выражения для проверки правильности выражения электронной почты с элементами управления проверкой ASP.NET. Мне было интересно, какое выражение лучше с точки зрения производительности или у кого-то есть лучшее.

 - \w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
 - ^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$

Я пытаюсь избежать проблемы «экспоненциально медленного выражения», описанной в BCL Team Blog .

UPDATE

Основываясь на отзывах, я в итоге создал функцию для проверки правильности письма:

Public Function IsValidEmail(ByVal emailString As String, Optional ByVal isRequired As Boolean = False) As Boolean
    Dim emailSplit As String()
    Dim isValid As Boolean = True
    Dim localPart As String = String.Empty
    Dim domainPart As String = String.Empty
    Dim domainSplit As String()
    Dim tld As String

    If emailString.Length >= 80 Then
        isValid = False
    ElseIf emailString.Length > 0 And emailString.Length < 6 Then
        'Email is too short
        isValid = False
    ElseIf emailString.Length > 0 Then
        'Email is optional, only test value if provided
        emailSplit = emailString.Split(CChar("@"))

        If emailSplit.Count <> 2 Then
            'Only 1 @ should exist
            isValid = False
        Else
            localPart = emailSplit(0)
            domainPart = emailSplit(1)
        End If

        If isValid = False OrElse domainPart.Contains(".") = False Then
            'Needs at least 1 period after @
            isValid = False
        Else
            'Test Local-Part Length and Characters
            If localPart.Length > 64 OrElse ValidateString(localPart, ValidateTests.EmailLocalPartSafeChars) = False OrElse _
               localPart.StartsWith(".") OrElse localPart.EndsWith(".") OrElse localPart.Contains("..") Then
                isValid = False
            End If

            'Validate Domain Name Portion of email address
            If isValid = False OrElse _
               ValidateString(domainPart, ValidateTests.HostNameChars) = False OrElse _
               domainPart.StartsWith("-") OrElse domainPart.StartsWith(".") OrElse domainPart.Contains("..") Then
                isValid = False
            Else
                domainSplit = domainPart.Split(CChar("."))
                tld = domainSplit(UBound(domainSplit))

                ' Top Level Domains must be at least two characters
                If tld.Length < 2 Then
                    isValid = False
                End If
            End If
        End If
    Else
        'If no value is passed review if required
        If isRequired = True Then
            isValid = False
        Else
            isValid = True
        End If
    End If

    Return isValid
End Function

Примечания:

  • IsValidEmail более ограничен в отношении разрешенных символов, чем RFC, но он не проверяет все возможные недопустимые варианты использования этих символов

Ответы [ 9 ]

12 голосов
/ 02 июня 2009

Если вам интересно, почему этот вопрос вызывает так мало активности, это потому, что есть много других проблем, с которыми нужно разобраться, прежде чем вы начнете думать о производительности. Главным среди них является то, следует ли вам вообще использовать регулярные выражения для проверки адресов электронной почты - и единодушным является то, что вам не следует. Это намного сложнее, чем большинство людей ожидают, и, возможно, в любом случае бессмысленно.

Другая проблема заключается в том, что ваши два регулярных выражения сильно различаются по типам строк, которые могут им соответствовать. Например, второй закреплен на обоих концах, но первый - нет; он будет соответствовать ">>>>foo@bar.com<<<<", потому что в нем есть что-то похожее на адрес электронной почты. Может быть, каркас заставляет регулярное выражение совпадать со всей строкой, но если это так, почему второй привязывается?

Другое отличие состоит в том, что первое регулярное выражение использует \w, в то время как второе использует [0-9a-zA-Z] во многих местах. В большинстве разновидностей регулярных выражений \w соответствует символу подчеркивания в дополнение к буквам и цифрам, но в некоторых (включая .NET) он также соответствует буквам и цифрам из всех систем записи, известных Unicode.

Есть много других отличий, но это академическое; ни одно из этих регулярных выражений не очень хорошо. См. здесь для хорошего обсуждения темы и гораздо лучшего выражения.

Возвращаясь к исходному вопросу, я не вижу проблемы производительности ни с одним из этих регулярных выражений. Помимо паттерна вложенных квантификаторов, упомянутого в этой записи блога BCL, следует также следить за ситуациями, когда две или более смежные части регулярного выражения могут совпадать с одним и тем же набором символов - например,

([A-Za-z]+|\w+)@

Ничего подобного нет ни в одном из приведенных вами регулярных выражений. Части, которые контролируются квантификаторами, всегда разбиваются другими частями, которые не определены количественно. Оба регулярных выражения будут испытывать некоторый возможный возврат назад, но есть много более веских причин, чем производительность, чтобы отклонить их.

РЕДАКТИРОВАТЬ: Таким образом, второе регулярное выражение является подлежит катастрофической откат назад; Я должен был тщательно проверить это, прежде чем откусить мне рот. Присмотревшись к этому регулярному выражению, я не понимаю, зачем вам нужна внешняя звездочка в первой части:

[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*

Все, что делает этот бит, - это убедиться, что первый и последний символы являются буквенно-цифровыми, а некоторые дополнительные символы между ними. Эта версия делает то же самое, но она терпит неудачу намного быстрее, когда никакое совпадение невозможно:

[0-9a-zA-Z][-.\w]*[0-9a-zA-Z]

Этого, вероятно, будет достаточно для устранения проблемы с возвратом, но вы также можете сделать деталь после "@" более эффективной, используя атомарную группу:

(?>(?:[0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+)[a-zA-Z]{2,9}

Другими словами, если вы сопоставили все, что могли, из подстрок, которые выглядят как компоненты домена, с конечными точками, а следующая часть не выглядит как TLD, не беспокойтесь о возврате. Первый символ, от которого вам придется отказаться, - это последняя точка, и вы знаете, что [a-zA-Z]{2,9} не будет соответствовать этому.

8 голосов
/ 23 июня 2010

Мы используем этот RegEx, который был протестирован на 1,5 млн. Адресов. Это правильно идентифицирует лучше, чем 98% наших, но есть некоторые форматы, о которых мне известно, что это приведет к ошибке.

^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$

Мы также следим за тем, чтобы в данных не было символов EOL, поскольку EOL может подделать этот RegEx. Наша функция:

Public Function IsValidEmail(ByVal strEmail As String) As Boolean
    ' Check An eMail Address To Ensure That It Is Valid
    Const cValidEmail = "^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$"   ' 98% Of All Valid eMail Addresses
    IsValidEmail = False
    ' Take Care Of Blanks, Nulls & EOLs
    strEmail = Replace(Replace(Trim$(strEmail & " "), vbCr, ""), vbLf, "")
    ' Blank eMail Is Invalid
    If strEmail = "" Then Exit Function
    ' RegEx Test The eMail Address
    Dim regEx As New System.Text.RegularExpressions.Regex(cValidEmail)
    IsValidEmail = regEx.IsMatch(strEmail)
End Function
2 голосов
/ 23 ноября 2012

Я новичок, но я попробовал следующее, и он, по-видимому, ограничил ".xxx" только двумя вхождениями или меньше после символа'@'.

^([a-zA-Z0-9]+[a-zA-Z0-9._%-]*@(?:[a-zA-Z0-9-])+(\.+[a-zA-Z]{2,4}){1,2})$

Примечание: мне пришлось заменить один '\' на двойной '\\', так как я использую этот регистр в R.

1 голос
/ 23 января 2013

Для проверки на стороне сервера я нашел решение Фила Хаака одним из лучших. Его попытка состояла в том, чтобы придерживаться RFC:

string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
return regex.IsMatch(emailAddress);

Подробнее: http://blog.degree.no/2013/01/email-validation-finally-a-net-regular-expression-that-works/

1 голос
/ 26 июня 2010

Я позволил MS сделать работу за меня:

Public Function IsValidEmail(ByVal emailString As String) As Boolean
    Dim retval As Boolean = True
    Try
        Dim address As New System.Net.Mail.MailAddress(emailString)
    Catch ex As Exception
        retval = False
    End Try
    Return retval
End Function
1 голос
/ 11 сентября 2009

Они не проверяют все допустимые адреса электронной почты в соответствии с адресом электронной почты RFC .

0 голосов
/ 22 декабря 2014

TextBox: -

<asp:TextBox ID="txtemail" runat="server" CssClass="form-control pantxt" Placeholder="Enter Email Address"></asp:TextBox>

Требуется Поданный валидатор:

<asp:RequiredFieldValidator ID="RequiredFieldValidator9" runat="server" ControlToValidate="txtemail" ErrorMessage="Required"></asp:RequiredFieldValidator>

Регулярное выражение для проверки электронной почты:

<asp:RegularExpressionValidator ID="validateemail" runat="server" ControlToValidate="txtemail" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" ErrorMessage="Invalid Email"></asp:RegularExpressionValidator>

Используйте это регулярное выражение для проверки электронной почты в asp.net

0 голосов
/ 13 февраля 2014

Дело в том, что спецификации меняются с каждым введенным расширением домена.

Вы сидите здесь, мод вашего регулярного выражения, тестирование, тестирование, тестирование и другие тесты. Вы, наконец, получаете то, что «считаете» точным, тогда спецификация меняется ... Вы обновляете свое регулярное выражение, чтобы учесть новые требования ..

Тогда кто-то входит в aa@aa.aa, и вы проделали всю эту работу для чего? Он прогуливается по твоему причудливому регулярному выражению .. Облом!

Вы также можете просто проверить наличие одного @ и "." и двигаться дальше. Уверяю вас, вы не получите кому-то электронное письмо, если они не захотят отказаться от него. Вы получите мусор или их учетную запись hotmail, которую они никогда не проверяют и не заботятся о ней.

Я видел, что во многих случаях это идет ужасно неправильно, и клиент звонит, потому что его собственный адрес электронной почты отклонен из-за неправильно созданной проверки регулярного выражения. Который, как уже упоминалось, даже не пытался.

0 голосов
/ 02 июня 2009

Просто чтобы внести свой вклад, я использую это регулярное выражение.

^([a-zA-Z0-9]+[a-zA-Z0-9._%-]*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,4})$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...