Проверка строк на соответствие формату электронной почтыHow to verify that strings are in valid email format

В следующем примере регулярное выражение используется, чтобы проверить, имеет ли строка допустимый формат адреса электронной почты.The following example uses a regular expression to verify that a string is in valid email format.

ПримерExample

В примере определяется метод IsValidEmail , который возвращает значение true , если строка содержит допустимый адрес электронной почты, и значение false , если она его не содержит, но не выполняет никаких других действий.The example defines an IsValidEmail method, which returns true if the string contains a valid email address and false if it does not, but takes no other action.

Чтобы проверить, что адрес электронной почты допустим, метод IsValidEmail вызывает метод Regex.Replace(String, String, MatchEvaluator) с шаблоном регулярного выражения (@)(.+)$ для выделения доменного имени из адреса электронной почты.To verify that the email address is valid, the IsValidEmail method calls the Regex.Replace(String, String, MatchEvaluator) method with the (@)(.+)$ regular expression pattern to separate the domain name from the email address. Третий параметр — это делегат MatchEvaluator , представляющий метод, который обрабатывает и заменяет найденный текст.The third parameter is a MatchEvaluator delegate that represents the method that processes and replaces the matched text. Шаблон регулярного выражения интерпретируется следующим образом.The regular expression pattern is interpreted as follows.

ШаблонPattern Описание:Description
(@) Совпадение с символом @.Match the @ character. Это первая группа записи.This is the first capturing group.
(.+) Совпадение с одним или несколькими вхождениями любого символа.Match one or more occurrences of any character. Это вторая группа записи.This is the second capturing group.
$ Совпадение должно заканчиваться в конце строки.End the match at the end of the string.

Доменное имя вместе с символом @ передается методу DomainMapper , который использует класс IdnMapping для преобразования символов Юникода, находящихся вне диапазона символов US-ASCII, в формат Punycode.The domain name along with the @ character is passed to the DomainMapper method, which uses the IdnMapping class to translate Unicode characters that are outside the US-ASCII character range to Punycode. Метод также устанавливает флаг invalid в значение True, если метод IdnMapping.GetAscii находит какие-либо недопустимые символы в доменном имени.The method also sets the invalid flag to True if the IdnMapping.GetAscii method detects any invalid characters in the domain name. Метод возвращает доменное имя в формате Punycode, которому предшествует символ @, методу IsValidEmail .The method returns the Punycode domain name preceded by the @ symbol to the IsValidEmail method.

Метод IsValidEmail затем вызывает метод Regex.IsMatch(String, String), чтобы убедиться, что адрес соответствует шаблону регулярного выражения.The IsValidEmail method then calls the Regex.IsMatch(String, String) method to verify that the address conforms to a regular expression pattern.

Обратите внимание, что метод IsValidEmail не выполняет аутентификацию для проверки действительности адреса электронной почты.Note that the IsValidEmail method does not perform authentication to validate the email address. Он просто проверяет, является ли его формат допустимым для адреса электронной почты.It merely determines whether its format is valid for an email address. Кроме того, метод IsValidEmail не проверяет, является ли доменное имя верхнего уровня действительным доменным именем, присутствующим в базе данных корневых зон IANA, что потребовало бы операции поиска.In addition, the IsValidEmail method does not verify that the top-level domain name is a valid domain name listed at the IANA Root Zone Database, which would require a look-up operation. Вместо этого регулярное выражение просто проверяет, что доменное имя верхнего уровня состоит из алфавитно-цифровых символов ASCII в количестве от двух до двадцати четырех, при этом первый и последний символ — это буква или цифра, а остальные символы — это буква, цифра или дефис (-).Instead, the regular expression merely verifies that the top-level domain name consists of between two and twenty-four ASCII characters, with alphanumeric first and last characters and the remaining characters being either alphanumeric or a hyphen (-).

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

public 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)
                var 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,
                @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
                @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
                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,
                                 "^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
                                 "(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
                                 RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250))

        Catch e As RegexMatchTimeoutException
            Return False

        End Try

    End Function

End Class

Возможные интерпретации шаблона регулярного выражения ^(?(")(".+?(?<!\\)"@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$ в этом примере показаны в следующей легенде.In this example, the regular expression pattern ^(?(")(".+?(?<!\\)"@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$ is interpreted as shown in the following legend. Регулярное выражение компилируется с флагом RegexOptions.IgnoreCase.The regular expression is compiled using the RegexOptions.IgnoreCase flag.

Шаблон ^: Соответствие должно обнаруживаться в начале строки.Pattern ^: Begin the match at the start of the string.

Шаблон (?("): Определение, является ли первый символ кавычкой.Pattern (?("): Determine whether the first character is a quotation mark. (?(") является началом конструкции изменения.(?(") is the beginning of an alternation construct.

Шаблон (?(")(".+?(?<!\\)"@): Если первый символ является кавычкой, совпадение с открывающей кавычкой, после которой следует как минимум одно вхождение любого символа с последующей закрывающей кавычкой.Pattern (?(")(".+?(?<!\\)"@): If the first character is a quotation mark, match a beginning quotation mark followed by at least one occurrence of any character, followed by an ending quotation mark. Последней закрывающей кавычки не должен предшествовать символ обратной косой черты (\).The ending quotation mark must not be preceded by a backslash character (\). (?<! — это начало утверждения отрицательного просмотра назад нулевой ширины.(?<! is the beginning of a zero-width negative lookbehind assertion. Строка должна заканчиваться знаком @.The string should conclude with an at sign (@).

Шаблон |(([0-9a-z]: Если первый символ не является кавычкой, имеется соответствие любой буквы с A до Z (при сравнении учитывается регистр) или любой цифре от 0 до 9.Pattern |(([0-9a-z]: If the first character is not a quotation mark, match any alphabetic character from a to z or A to Z (the comparison is case insensitive), or any numeric character from 0 to 9.

Шаблон (\.(?!\.)): Если следующим символом является точка, имеется соответствие.Pattern (\.(?!\.)): If the next character is a period, match it. Если этот символ не является точкой, выполняется поиск вперед к следующему символу и продолжается поиск соответствия.If it is not a period, look ahead to the next character and continue the match. (?!\.) является утверждением отрицательного поиска вперед нулевой ширины, предотвращающим отображение двух последовательных точек в локальной части адреса электронной почты.(?!\.) is a zero-width negative lookahead assertion that prevents two consecutive periods from appearing in the local part of an email address.

Шаблон |[-!#\$%&'\*\+/=\?\^`\{\}\|~\w]: Если следующий символ не является точкой, сопоставьте его с любым символом слова или одним из следующих символов: -!#$%&'*+/=?^`{}|~.Pattern |[-!#\$%&'\*\+/=\?\^`\{\}\|~\w]: If the next character is not a period, match any word character or one of the following characters: -!#$%&'*+/=?^`{}|~

Шаблон ((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*: Соответствие шаблону изменения (точка, после которой следует символ, отличный от точки, или одна цифра) 0 или несколько раз.Pattern ((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*: Match the alternation pattern (a period followed by a non-period, or one of a number of characters) zero or more times.

Шаблон @: Совпадение с символом @.Pattern @: Match the @ character.

Шаблон (?<=[0-9a-z]): Продолжение поиска соответствия, если символ, предшествующий символу @, является буквой от A до Z, от a до z или цифрой от 0 до 9.Pattern (?<=[0-9a-z]): Continue the match if the character that precedes the @ character is A through Z, a through z, or 0 through 9. Этот шаблон определяет положительное утверждение просмотра назад нулевой ширины.This pattern defines a zero-width positive lookbehind assertion.

Шаблон (?(\[): Проверка, является ли символ, следующий после символа @, открывающей круглой скобкой.Pattern (?(\[): Check whether the character that follows @ is an opening bracket.

Шаблон (\[(\d{1,3}\.){3}\d{1,3}\]): Если этот символ является открывающей круглой скобкой, имеется соответствие открытой круглой скобки, после которой идет IP-адрес (четыре группы из одной-трех цифр, разделенные точкой) и закрывающая круглая скобка.Pattern (\[(\d{1,3}\.){3}\d{1,3}\]): If it is an opening bracket, match the opening bracket followed by an IP address (four sets of one to three digits, with each set separated by a period) and a closing bracket.

Шаблон |(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+: Если символ, следующий за @, не является открывающей круглой скобкой, совпадение с одним буквенно-цифровым символом со значением A–Z, a-z или 0–9, за которым следует ноль или несколько вхождений или дефиса, за которыми следует ноль или один буквенно-цифровой символ со значением A–Z, a-z или 0–9 с последующей точкой.Pattern |(([0-9a-z][-0-9a-z]*[0-9a-z]*\.)+: If the character that follows @ is not an opening bracket, match one alphanumeric character with a value of A-Z, a-z, or 0-9, followed by zero or more occurrences of a hyphen, followed by zero or one alphanumeric character with a value of A-Z, a-z, or 0-9, followed by a period. Этот шаблон может повторяться один или больше раз и после него должно идти доменное имя верхнего уровня.This pattern can be repeated one or more times, and must be followed by the top-level domain name.

Шаблон [a-z0-9][\-a-z0-9]{0,22}[a-z0-9])): Доменное имя должно начинаться с буквы или цифры (a-z, A-Z и 0-9) и заканчиваться на букву или цифру.Pattern [a-z0-9][\-a-z0-9]{0,22}[a-z0-9])): The top-level domain name must begin and end with an alphanumeric character (a-z, A-Z, and 0-9). В него также может входить от 0 до 22 ASCII-символов, которые могут быть буквами, цифрами или дефисом.It can also include from zero to 22 ASCII characters that are either alphanumeric or hyphens.

Шаблон $: Совпадение должно заканчиваться в конце строки.Pattern $: End the match at the end of the string.

Компиляция кодаCompile the code

Методы IsValidEmail и DomainMapper можно включить в библиотеку служебных методов регулярных выражений или в класс приложения в качестве закрытых статических или экземплярных методов.The IsValidEmail and DomainMapper methods can be included in a library of regular expression utility methods, or they can be included as private static or instance methods in the application class.

Вы также можете использовать метод Regex.CompileToAssembly , чтобы включить это регулярное выражение в библиотеку регулярных выражений.You can also use the Regex.CompileToAssembly method to include this regular expression in a regular expression library.

Если они используются в библиотеке регулярных выражений, их можно вызывать с помощью кода, например, следующим образом:If they are used in a regular expression library, you can call them by using code such as the following:

class Program
{
    static void Main(string[] args)
    {
        string[] emailAddresses = { "david.jones@proseware.com", "d.j@server1.proseware.com",
                                    "jones@ms1.proseware.com", "j.@server1.proseware.com",
                                    "j@proseware.com9", "js#internal@proseware.com",
                                    "j_9@[129.126.118.1]", "j..s@proseware.com",
                                    "js*@proseware.com", "js@proseware..com",
                                    "js@proseware.com9", "j.s@server1.proseware.com",
                                    "\"j\\\"s\\\"\"@proseware.com", "js@contoso.中国" };

        foreach (var emailAddress in emailAddresses)
        {
            if (RegexUtilities.IsValidEmail(emailAddress))
                Console.WriteLine($"Valid:   {emailAddress}");
            else
                Console.WriteLine($"Invalid: {emailAddress}");
        }

        Console.ReadKey();
    }
}
// The example displays the following output:
//       Valid: david.jones@proseware.com
//       Valid: d.j@server1.proseware.com
//       Valid: jones@ms1.proseware.com
//       Invalid: j.@server1.proseware.com
//       Valid: j@proseware.com9
//       Valid: js#internal@proseware.com
//       Valid: j_9@[129.126.118.1]
//       Invalid: j..s@proseware.com
//       Invalid: js*@proseware.com
//       Invalid: js@proseware..com
//       Valid: js@proseware.com9
//       Valid: j.s@server1.proseware.com
//       Valid: "j\"s\""@proseware.com
//       Valid: js@contoso.中国
Public Class Application
   Public Shared Sub Main()
      Dim emailAddresses() As String = {"david.jones@proseware.com", "d.j@server1.proseware.com",
                                       "jones@ms1.proseware.com", "j.@server1.proseware.com",
                                       "j@proseware.com9", "js#internal@proseware.com",
                                       "j_9@[129.126.118.1]", "j..s@proseware.com",
                                       "js*@proseware.com", "js@proseware..com",
                                       "js@proseware.com9", "j.s@server1.proseware.com",
                                       """j\""s\""""@proseware.com", "js@contoso.中国"}

      For Each emailAddress As String In emailAddresses
         If RegexUtilities.IsValidEmail(emailAddress) Then
               Console.WriteLine($"Valid:   {emailAddress}")
         Else
               Console.WriteLine($"Invalid: {emailAddress}")
         End If
      Next
   End Sub
End Class
' The example displays the following output:
'       Valid: david.jones@proseware.com
'       Valid: d.j@server1.proseware.com
'       Valid: jones@ms1.proseware.com
'       Invalid: j.@server1.proseware.com
'       Valid: j@proseware.com9
'       Valid: js#internal@proseware.com
'       Valid: j_9@[129.126.118.1]
'       Invalid: j..s@proseware.com
'       Invalid: js*@proseware.com
'       Invalid: js@proseware..com
'       Valid: js@proseware.com9
'       Valid: j.s@server1.proseware.com
'       Valid: "j\"s\""@proseware.com
'       Valid: js@contoso.中国

См. такжеSee also