2009-06-01 17 views
7

He utilizado las dos expresiones regulares siguientes para probar una expresión de correo electrónico válida con controles de validación de ASP.NET. Me preguntaba cuál es la mejor expresión desde el punto de vista del rendimiento, o si alguien tiene una mejor.Mejor expresión regular para la validación del formato de correo electrónico con Validación de ASP.NET 3.5

 
- \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})$ 

Estoy tratando de evitar el problema "de manera exponencial lenta expresión" que se describe en la BCL Team Blog.

ACTUALIZACIÓN

basado en la retroalimentación que terminé creando una función para comprobar si un correo electrónico es válida:

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 

Notas:

  • IsValidEmail es más restrictiva sobre caracteres permitidos luego el RFC, pero no prueba todos los posibles usos no válidos de esos caracteres
+0

posible duplicado de [Expresión regular mejor para el correo de validación en C#] (http: // stackoverflow .com/questions/16167983/best-regular-expression-for-email-validation-in-c-sharp) – Milad

Respuesta

12

Si usted se pregunta por qué esta pregunta está generando tan poca actividad, que se debe a que hay tantas otras cuestiones que deben tratarse antes de empezar a pensar en el rendimiento. Lo más importante entre ellos es si debería usar expresiones regulares para validar direcciones de correo electrónico, y el consenso es que no debería hacerlo. Es mucho más complicado de lo que la mayoría de la gente espera, y probablemente sin sentido de todos modos.

Otro problema es que sus dos expresiones regulares varían enormemente en los tipos de cadenas que pueden coincidir. Por ejemplo, el segundo está anclado en ambos extremos, pero el primero no; coincidiría con ">>>>[email protected]<<<<" porque hay algo que parece una dirección de correo electrónico incrustada en él. Tal vez el marco obligue a la expresión regular a coincidir con toda la cadena, pero si ese es el caso, ¿por qué está anclada la segunda?

Otra diferencia es que la primera expresión regular usa \w en todas partes, mientras que la segunda usa [0-9a-zA-Z] en muchos lugares. En la mayoría de los sabores de expresiones regulares, \w coincide con el guión bajo además de las letras y los dígitos, pero en algunos (incluido .NET) también coincide con letras y dígitos de todos los sistemas de escritura conocidos por Unicode.

Hay muchas otras diferencias, pero eso es académico; ninguna de esas expresiones regulares es muy buena. Vea here para una buena discusión del tema, y ​​una expresión regular mucho mejor.

Volviendo a la pregunta original, no veo un problema de rendimiento con cualquiera de esas expresiones regulares. Aparte de la anidados-cuantificadores anti-patrón citado en esa entrada de blog BCL, también debe mirar hacia fuera para situaciones en las que dos o más partes adyacentes de la expresión regular puede coincidir con el mismo conjunto de caracteres - por ejemplo,

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

No hay nada como eso en ninguna de las expresiones regulares que publicaste. Las partes que están controladas por cuantificadores siempre se dividen por otras partes que no están cuantificadas. Ambas expresiones regulares experimentarán un retroceso evitable, pero existen muchas más razones para rechazarlas que el rendimiento.

EDITAR: Por lo tanto, la segunda expresión regular es sujeta a retroceso catastrófico; Debería haberlo probado a fondo antes de dispararme la boca. Echando un vistazo más de cerca a esa expresión regular, no veo por qué necesita el asterisco exterior en la primera parte:

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

Todo lo que hace es poco asegurarse de que los primeros y últimos caracteres alfanuméricos al tiempo que permite que algunos caracteres adicionales entre. Esta versión hace lo mismo, pero no mucho más rápidamente cuando hay coincidencia es posible:

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

Eso probablemente sería suficiente para eliminar el problema marcha atrás, pero también se puede hacer la parte después de la "@" más eficiente mediante el uso de un grupo atómico:

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

En otras palabras, si usted ha emparejado todo lo que pueda de subcadenas que se parecen a los componentes de dominio con los puntos de fuga, y la siguiente parte no se ve como un TLD, don' Me molesto en retroceder. El primer personaje al que tendrías que renunciar es el punto final, y sabes que [a-zA-Z]{2,9} no coincidirá con eso.

+0

He estado debatiendo la creación de un Validador personalizado, con una verificación del lado del servidor utilizando una prueba de correo electrónico no RegEx. Después de la prueba, encontré que la segunda expresión puede crear una "expresión exponencialmente lenta" (dada la entrada correcta) con JavaScript o con el proceso .NET en el servidor, en el que el proceso crea lo que parece ser un proceso congelado. – Josh

0

Solo para contribuir, estoy usando esta expresión regular.

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

Valida [email protected], que es el compañero equivocado ... es posible restringir al usuario para ingresar más de 2 puntos después de @ –

1

Estos no verifican todas las direcciones de correo electrónico permitidas de acuerdo con email address RFC.

+1

¿Tiene un RegEx o una serie de ellos que lo haría? – Dave

+0

Aquí hay un comienzo ...: /([!#-'*+.-9=?AZ^-~-]{1,64}|"[^"]{1,62}")@[a -zA-Z] [a-zA-Z0-9 .-] {1,255}/ En la primera parte, el período no puede ser el primero ni el último. – kzh

8

Usamos este RegEx que ha sido probado internamente contra 1,5 millones de direcciones. Identifica correctamente mejor que el 98% de los nuestros, pero hay algunos formatos de los que soy consciente de que se produciría un error.

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

También nos aseguramos de que no hay caracteres EOL en los datos ya que un EOL se puede fingir a cabo esta RegEx. Nuestra Función:

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 
+0

Funciona muy bien, gracias por la expresión regular. – TheGateKeeper

+0

Esto debe ser actualizado para TLD más largos ahora. Hay muchos más TLD disponibles que tienen más de 6 caracteres ahora. Configuré el mío a 20. ^ ([\ w -] + (?: \. [\ w -] +) *) @ ((?: [\ w -] + \.) * \ w [\ w -] {0,66}) \. ([az] {2,20} (?: \. [az] {2}) ?) $ http://newgtlds.icann.org/en/program-status/delegated-strings – 2GDave

+0

Nuestra base de datos es la razón principal por la que la dirección de correo electrónico se define tan corta como es. La base de datos se creó originalmente de nuevo. los años 90 y se combinó con MS-Dynamics que agregó complicaciones – Dave

1

dejo MS para hacer el trabajo para mí:

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 
+0

Buena idea, no me di cuenta de que el objeto de dirección tenía una validación incorporada. Mi única preocupación es que debe usar la gestión de excepciones para el flujo de trabajo normal. – Josh

+0

No, he intentado con las direcciones de correo electrónico que no eran válidas (algo @ .com creo que fue una de ellas). Sin excepción, logró crear el objeto. Esto estaba en C#, pero suponiendo que VB es el mismo. – Andreas

+0

Andreas, por supuesto que es lo mismo en VB. Hay una clase MailAddress en .NET framework, y puede usarla desde cualquier lenguaje .NET. –

2

Yo soy muy novato, pero me trató lo siguiente y parecía haber limitado el ".xxx" para solamente dos apariciones o menos, después del símbolo '@'.

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

Nota: tuve que sustituir single '\' con doble '\\' como yo estoy usando este expr reg en R.

1

Para la validación del lado del servidor, encontré la solución de Phil Haack ser uno de los mejores. Su intento fue a pegarse a la 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); 

Detalles: http://blog.degree.no/2013/01/email-validation-finally-a-net-regular-expression-that-works/

0

Lo que pasa es que las especificaciones están cambiando con cada extensión de dominio que se introduce.

Usted se sienta aquí mod su regex, prueba, prueba, prueba, y más pruebas. Finalmente obtiene lo que "piensa" es preciso entonces los cambios de especificación ... que actualice su expresión regular para dar cuenta de lo que los nuevos requisitos son ..

Entonces alguien entra [email protected] y que has hecho todo lo que trabajar para qué? Camina a través de su regex de lujo ... ¡Qué fastidio!

También puede comprobar si hay una sola @ y una "."y seguir. Te aseguro que no recibirás correos electrónicos de alguien si no quiere renunciar a ellos. Recibirás basura o su cuenta de Hotmail que nunca revisan y no podrían importarle menos.

I he visto en muchos casos, esto va muy mal y un cliente llama a causa de su propia dirección de correo electrónico es rechazado debido a una comprobación de expresiones regulares mal diseñado que como debería ni siquiera se han intentado mencionado

0

Cuadro de texto: -..

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

Requerido validador archivado:

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

de expresiones regulares para la validación de correo electrónico:

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

uso esta expresión regular para la validación de correo electrónico en asp.net

Cuestiones relacionadas