2009-06-01 17 views
7

Ho utilizzato entrambe le seguenti espressioni regolari per il test di un'espressione di posta elettronica valida con controlli di convalida ASP.NET. Mi stavo chiedendo quale sia l'espressione migliore dal punto di vista delle prestazioni, o se qualcuno ne ha una migliore.Migliore espressione regolare per convalida formato e-mail con convalida 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})$ 

sto cercando di evitare la "espressione esponenzialmente lento" problema descritto sul BCL Team Blog.

UPDATE

in base al feedback Ho finito per creare una funzione per verificare se una e-mail valida:

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 

Note:

  • IsValidEmail è più restrittivo sui caratteri consentiti quindi la RFC, ma non verifica tutti i possibili usi non validi di quei caratteri
+0

possibile duplicato di [Best Regular Expression per Email Validation in C#] (http: // StackOverflow .com/domande/16167983/best-regular-expression-per-email-validazione-in-c-sharp) – Milad

risposta

12

Se vi state chiedendo il motivo per cui questa domanda sta generando così poca attività, è perché ci sono tanti altri problemi che devono essere affrontati prima di iniziare a pensare a prestazioni. Primo fra tutti è se dovresti usare le espressioni regolari per convalidare gli indirizzi e-mail - e il consenso è che non dovresti. È molto più complicato di quanto la maggior parte della gente si aspetti, e probabilmente inutile comunque.

Un altro problema è che le due regex variano enormemente nel tipo di stringhe che possono corrispondere. Ad esempio, il secondo è ancorato ad entrambe le estremità, ma il primo non lo è; corrisponderebbe a ">>>>[email protected]<<<<" perché c'è qualcosa che assomiglia ad un indirizzo email incorporato. Forse la struttura costringe la regex a far corrispondere l'intera stringa, ma se questo è il caso, perché il secondo è ancorato?

Un'altra differenza è che il primo regex utilizza \w in tutto, mentre il secondo utilizza [0-9a-zA-Z] in molti luoghi. Nella maggior parte dei sapori regex, \w corrisponde al sottolineatura oltre a lettere e cifre, ma in alcuni (tra cui .NET) corrisponda anche lettere e cifre provenienti da ogni sistema di scrittura noto a Unicode.

Ci sono molte altre differenze, ma questo è accademico; nessuna di queste regex è molto buona. Vedi here per una buona discussione dell'argomento e una regex molto migliore.

Tornando alla domanda iniziale, non vedo una performance problema con uno di quei regex. A parte il nested-quantificatori anti-modello citato in quella voce BCL blog, si dovrebbe anche guardare fuori per situazioni in cui due o più parti adiacenti del regex può eguagliare lo stesso set di caratteri - per esempio,

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

Non c'è niente di simile in nessuna delle regex che hai postato. Le parti controllate dai quantificatori sono sempre suddivise da altre parti non quantificate. Entrambe le regex subiranno alcuni backtrack evitabili, ma ci sono molti motivi migliori delle prestazioni per rifiutarli.

MODIFICA: Quindi la seconda regex è soggetta a backtracking catastrofico; Avrei dovuto provarlo a fondo prima di spararmi. Dando uno sguardo più da vicino a quel regex, non vedo il motivo per cui è necessario l'asterisco esterna nella prima parte:

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

Tutto quel po 'non fa altro che assicurarsi che il primo e l'ultimo carattere sono alfanumerici, consentendo alcuni caratteri aggiuntivi nel mezzo. Questa versione fa la stessa cosa, ma non riesce molto più rapidamente quando nessun match è possibile:

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

che probabilmente sufficiente a eliminare il problema backtracking, ma si potrebbe anche fare la parte dopo il simbolo "@" più efficiente utilizzando un gruppo atomica:

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

In altre parole, se hai abbinato tutto il possibile di sottostringhe che assomigliano a componenti di dominio con punti finali, e la parte successiva non sembra un dominio di primo livello, don' t preoccuparsi di tornare indietro. Il primo carattere che dovresti rinunciare è il punto finale, e sai che lo [a-zA-Z]{2,9} non corrisponderà a quello.

+0

Sto discutendo la creazione di un validatore personalizzato, con un controllo lato server utilizzando un test non RegEx e-mail. Dopo la prova, ho trovato la seconda espressione può creare un "modo esponenziale lenta espressione" (dato l'input a destra) con JavaScript o con processo .NET sul server, in cui il trattamento crea quello che sembra essere processo di congelamento. – Josh

0

Solo per contribuire, io sto usando questo regex.

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

si convalida [email protected] che è compagno di sbagliato ... E ' possibile limitare all'utente di inserire più di 2 punti dopo @ –

1

Questi non controllano tutti gli indirizzi di posta elettronica consentiti in base allo email address RFC.

+1

Avete una RegEx o una serie di essi che farebbe? – Dave

+0

Qui è un inizio ...: /([!#-'*+.-9=?AZ^-~-]{1,64}|"[^"]{1,62}")@[a -zA-Z] [a-zA-Z0-9 .-] {1,255}/ Nella prima parte, il periodo non può essere il primo o l'ultimo – kzh

8

Usiamo questo RegEx che è stato testato internamente contro 1,5 milioni di indirizzi. Identifica correttamente meglio del 98% dei nostri, ma ci sono alcuni formati di cui sono a conoscenza che si verificherebbero errori.

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

Abbiamo anche fare in modo che non vi siano caratteri EOL nei dati dal momento che un EOL può fingere questo RegEx. La nostra funzione:

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

Funziona ottimo amico, grazie per il regex – TheGateKeeper

+0

Questo deve essere .. aggiornati per TLD più lunghi ora ci sono molti altri TLD disponibili che sono oltre 6 caratteri ora mia ho impostato 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

il nostro database è la ragione principale che l'indirizzo e-mail è definito come breve come è. il database è stato originariamente costruito nel gli anni 90 ed è stato abbinato a MS-Dynamics che ha aggiunto ulteriormente complicazioni. – Dave

1

ho lasciato gli Stati membri a fare il lavoro per me:

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

Buona idea, non mi ero reso conto che l'oggetto indirizzo aveva la convalida integrata. La mia unica preoccupazione è che devi usare la gestione delle eccezioni per il normale flusso di lavoro. – Josh

+0

Non è così, ho provato quello con gli indirizzi e-mail che non erano validi (qualcosa @ .com credo fosse uno di loro). Nessuna eccezione, è riuscito a creare l'oggetto. Questo era in C#, ma assumere VB è lo stesso. – Andreas

+0

Andreas, ovviamente è lo stesso in VB. Esiste una classe MailAddress nel framework .NET e puoi usarla da qualsiasi linguaggio .NET. –

2

Sono un novizio, ma ho provato quanto segue e che sembrava aver limitato la ".xxx" a solo due occorrenze o meno, dopo il simbolo '@'.

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

Nota: ho dovuto sostituire singolo '\' con il doppio '\\' come Sto usando questo reg expr in R.

1

Per la validazione lato server, ho trovato la soluzione di Phil Haack essere uno dei migliori Il suo tentativo è stato quello di aderire alla 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); 

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

0

La cosa a questo proposito è specifiche stanno cambiando con l'estensione del dominio che viene introdotto.

Siedi qui mod la tua regex, test, test, test e più test. Finalmente ottieni ciò che "pensi" sia accurato allora le specifiche cambiano ... Aggiorni la tua regex per tenere conto di quali sono i nuovi requisiti ..

Poi qualcuno entra [email protected] e tu hai fatto tutto ciò lavoro per cosa? Passa attraverso la tua regex di fantasia ... peccato!

Si può anche controllare un singolo @, e un ".Ti assicuro che non riceverai email di qualcuno se non vogliono rinunciare. Otterrai la spazzatura o il loro account di Hotmail che non controlleranno mai e di cui non potrebbero importare di meno

I 'ho visto in molti casi questo va terribilmente male e un client richiama perché il loro indirizzo di posta elettronica viene rifiutato a causa di un controllo regex mal messo che come detto dovrebbe non sono stati nemmeno tentato

0

TextBox: -..

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

Richiesto validatore Archiviato:

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

Regular Expression per la convalida e-mail:

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

Utilizzare questa espressione regolare per la convalida e-mail in asp.net

Problemi correlati