Come verificare che le stringhe siano in formato di posta elettronica valido

L'esempio di questo articolo usa un'espressione regolare per verificare la validità del formato di posta elettronica di una stringa.

Questa espressione regolare è relativamente semplice rispetto a ciò che può essere effettivamente usato come messaggio di posta elettronica. L'uso di un'espressione regolare per convalidare un messaggio di posta elettronica è utile per assicurarsi che la struttura di un messaggio sia corretta. Tuttavia, non può sostituire la verifica dell'effettiva esistenza del messaggio.

✔️ Usare un'espressione regolare semplice per verificare la validità della struttura di un messaggio di posta elettronica.

✔️ Inviare un messaggio di posta elettronica di prova all'indirizzo fornito da un utente dell'app.

❌ NON usare un'espressione regolare come unico modo per convalidare un messaggio di posta elettronica.

Se per verificare che la struttura di un messaggio di posta elettronica sia corretta si tenta di creare l'espressione regolare perfetta, questa diventa talmente complessa da essere incredibilmente difficile da sottoporre a debug o migliorare. Le espressioni regolari non possono convalidare l'esistenza di un messaggio di posta elettronica, anche se è strutturato correttamente. Il modo migliore per convalidare un messaggio di posta elettronica consiste nell'inviare un messaggio di prova all'indirizzo.

Avviso

Quando si usa System.Text.RegularExpressions per elaborare l'input non attendibile, passare un timeout. Un utente malintenzionato può fornire input a RegularExpressions, provocando un attacco Denial of Service. Le API del framework ASP.NET Core che usano RegularExpressions passano un timeout.

Esempio

Nell'esempio viene definito un metodo IsValidEmail che restituisce true se la stringa contiene un indirizzo di posta elettronica valido e false in caso contrario, ma non esegue alcuna altra azione.

Per verificare che l'indirizzo di posta elettronica sia valido, il metodo IsValidEmail chiama il metodo Regex.Replace(String, String, MatchEvaluator) con il criterio di espressione regolare (@)(.+)$ per separare il nome di dominio dall'indirizzo di posta elettronica. Il terzo parametro è un delegato MatchEvaluator che rappresenta il metodo che elabora e sostituisce il testo corrispondente. Il criterio dell'espressione regolare viene interpretato nel modo seguente:

Modello Descrizione
(@) Trova la corrispondenza con il carattere @. Questa parte è il primo gruppo di acquisizione.
(.+) Trova la corrispondenza con una o più occorrenze di qualsiasi carattere. Questa parte è il secondo gruppo di acquisizione.
$ Terminare la corrispondenza alla fine della stringa.

Il nome di dominio, insieme al carattere @, viene passato al metodo DomainMapper. Il metodo usa la classe IdnMapping per convertire i caratteri Unicode che si trovano all'esterno dell'intervallo di caratteri US-ASCII in Punycode. Il metodo imposta inoltre il flag invalid su True se il metodo IdnMapping.GetAscii rileva caratteri non validi nel nome di dominio. Il metodo restituisce il nome di dominio Punycode preceduto dal simbolo @ al metodo IsValidEmail .

Suggerimento

È consigliabile usare il criterio di espressione regolare semplice (@)(.+)$ per normalizzare il dominio e quindi restituire un valore che indica se è passato o non riuscito. Tuttavia, l'esempio in questo articolo descrive come usare ulteriormente un'espressione regolare per convalidare il messaggio di posta elettronica. Indipendentemente dalla modalità di convalida di un messaggio di posta elettronica, è consigliabile inviare sempre un messaggio di prova all'indirizzo per assicurarsi che esista.

Il metodo IsValidEmail chiama quindi il metodo Regex.IsMatch(String, String) per verificare che l'indirizzo sia conforme a un criterio di espressione regolare.

Il metodo IsValidEmail determina semplicemente se il formato di posta elettronica è valido per un indirizzo, ma non convalida l'esistenza del messaggio. Inoltre, il metodo IsValidEmail non verifica che il nome di dominio di primo livello sia un nome di dominio valido elencato nella pagina del Database delle aree radice sul sito IANA, cosa che richiederebbe un'operazione di ricerca.

using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace RegexExamples
{
    class RegexUtilities
    {
        public static bool IsValidEmail(string email)
        {
            if (string.IsNullOrWhiteSpace(email))
                return false;

            try
            {
                // Normalize the domain
                email = Regex.Replace(email, @"(@)(.+)$", DomainMapper,
                                      RegexOptions.None, TimeSpan.FromMilliseconds(200));

                // Examines the domain part of the email and normalizes it.
                string DomainMapper(Match match)
                {
                    // Use IdnMapping class to convert Unicode domain names.
                    var idn = new IdnMapping();

                    // Pull out and process domain name (throws ArgumentException on invalid)
                    string domainName = idn.GetAscii(match.Groups[2].Value);

                    return match.Groups[1].Value + domainName;
                }
            }
            catch (RegexMatchTimeoutException e)
            {
                return false;
            }
            catch (ArgumentException e)
            {
                return false;
            }

            try
            {
                return Regex.IsMatch(email,
                    @"^[^@\s]+@[^@\s]+\.[^@\s]+$",
                    RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
            }
            catch (RegexMatchTimeoutException)
            {
                return false;
            }
        }
    }
}
Imports System.Globalization
Imports System.Text.RegularExpressions

Public Class RegexUtilities
    Public Shared Function IsValidEmail(email As String) As Boolean

        If String.IsNullOrWhiteSpace(email) Then Return False

        ' Use IdnMapping class to convert Unicode domain names.
        Try
            'Examines the domain part of the email and normalizes it.
            Dim DomainMapper =
                Function(match As Match) As String

                    'Use IdnMapping class to convert Unicode domain names.
                    Dim idn = New IdnMapping

                    'Pull out and process domain name (throws ArgumentException on invalid)
                    Dim domainName As String = idn.GetAscii(match.Groups(2).Value)

                    Return match.Groups(1).Value & domainName

                End Function

            'Normalize the domain
            email = Regex.Replace(email, "(@)(.+)$", DomainMapper,
                                  RegexOptions.None, TimeSpan.FromMilliseconds(200))

        Catch e As RegexMatchTimeoutException
            Return False

        Catch e As ArgumentException
            Return False

        End Try

        Try
            Return Regex.IsMatch(email,
                                 "^[^@\s]+@[^@\s]+\.[^@\s]+$",
                                 RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250))

        Catch e As RegexMatchTimeoutException
            Return False

        End Try

    End Function
End Class

In questo esempio il modello di espressione regolare ^[^@\s]+@[^@\s]+\.[^@\s]+$ viene interpretato come illustrato nella tabella seguente. L'espressione regolare viene compilata usando il flag RegexOptions.IgnoreCase.

Modello Descrizione
^ Iniziare la ricerca della corrispondenza all'inizio della stringa.
[^@\s]+ Trova una o più occorrenze di qualsiasi carattere diverso da @ o dallo spazio vuoto.
@ Trova la corrispondenza con il carattere @.
[^@\s]+ Trova una o più occorrenze di qualsiasi carattere diverso da @ o dallo spazio vuoto.
\. Trova un singolo carattere punto.
[^@\s]+ Trova una o più occorrenze di qualsiasi carattere diverso da @ o dallo spazio vuoto.
$ Terminare la corrispondenza alla fine della stringa.

Importante

Questa espressione regolare non è progettata per coprire ogni aspetto di un indirizzo di posta elettronica valido. Viene fornita come esempio da estendere in base alle esigenze.

Vedi anche