Kod C # do weryfikacji adresu e-mail

461

Jaki jest najbardziej elegancki kod potwierdzający, że ciąg jest prawidłowym adresem e-mail?

leora
źródło
istnieje wiele innych ważnych walidacji, nie tylko ciąg, lepiej sprawdzić, czy wiadomość e-mail istnieje na tym serwerze smtp, czy użytkownik wprowadza jakąkolwiek wiadomość e-mail .. itp. lub użyć interfejsu API, który będzie to obsługiwał, aby mieć pewność, że wiadomość e-mail jest poprawny jak ver-email.com
Amr Magdy
Najlepsze informacje od Microsoft Docs.microsoft.com/en-us/dotnet/standard/base-types/…
Kishore Sahasranaman,
możesz użyć biblioteki github.com/jstedfast/EmailValidation .
Mohammad Reza Sadreddini,

Odpowiedzi:

783

A co z tym?

bool IsValidEmail(string email)
{
    try {
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == email;
    }
    catch {
        return false;
    }
}

Aby wyjaśnić, pytanie dotyczy tego, czy określony ciąg jest prawidłową reprezentacją adresu e-mail, a nie czy adres e-mail jest prawidłowym miejscem docelowym do wysłania wiadomości. W tym celu jedynym prawdziwym sposobem jest wysłanie wiadomości w celu potwierdzenia.

Pamiętaj, że adresy e-mail są bardziej wyrozumiałe, niż możesz przypuszczać. Są to wszystkie doskonale obowiązujące formularze:

  • tryb
  • „koło zębate pomarańczy” @ example.com
  • 123@$.xyz

W większości przypadków użycia fałszywa „nieprawidłowa” jest znacznie gorsza dla użytkowników i sprawdzania w przyszłości niż fałszywa „ważna”. Oto artykuł, który kiedyś był akceptowaną odpowiedzią na to pytanie (odpowiedź ta została już usunięta). Ma o wiele więcej szczegółów i kilka innych pomysłów na rozwiązanie problemu.

Zapewnienie kontroli poczytalności jest nadal dobrym pomysłem dla wygody użytkownika. Zakładając, że adres e-mail jest prawidłowy, możesz poszukać znanych domen najwyższego poziomu, sprawdzić domenę pod kątem rekordu MX, sprawdzić błędy ortograficzne w popularnych nazwach domen (gmail.cmo) itp. Następnie przedstaw ostrzeżenie dla użytkownika możliwość powiedzenia „tak, mój serwer pocztowy naprawdę pozwala 🌮🍳🎁 jako adres e-mail”.


Jeśli chodzi o korzystanie z obsługi wyjątków w logice biznesowej, zgadzam się, że należy tego unikać. Jest to jednak jeden z tych przypadków, w których wygoda i przejrzystość mogą przeważać nad dogmatem.

Poza tym, jeśli robisz cokolwiek innego z adresem e-mail, prawdopodobnie będzie to wymagało przekształcenia go w adres mailowy. Nawet jeśli nie użyjesz dokładnie tej funkcji, prawdopodobnie będziesz chciał użyć tego samego wzorca. Możesz także sprawdzić, czy nie występują określone rodzaje awarii, wychwytując różne wyjątki : zerowy, pusty lub nieprawidłowy format.


Według komentarza Stuarta porównuje on końcowy adres z oryginalnym ciągiem, zamiast zawsze zwracając wartość true. MailAddress próbuje parsować ciąg ze spacjami w częściach „Nazwa wyświetlana” i „Adres”, więc oryginalna wersja zwracała wyniki fałszywie dodatnie.


--- Dalsze czytanie ---

Dokumentacja dla System.Net.Mail.MailAddress

Wyjaśnienie, co stanowi prawidłowy adres e-mail

Tryb
źródło
23
Właściwie to nie jest nieprawidłowe. a @ a jest prawidłowym adresem e-mail. Zobacz haacked.com/archive/2007/08/21/... W rzeczywistości ta metoda zwraca nieprawidłowe wyniki, jeśli używasz adresu z cudzysłowami.
Koło zębate
53
+1: To najlepsza odpowiedź, jeśli używasz System.Net.Mailklas do wysyłania poczty, co prawdopodobnie jest, jeśli używasz platformy .NET. Podjęliśmy decyzję o zastosowaniu tego rodzaju sprawdzania poprawności po prostu dlatego, że nie ma sensu akceptować adresów e-mail - nawet tych ważnych - na które nie możemy wysyłać poczty.
Greg Beech
24
Nie polecam Zwraca prawdę:IsValidEmail("this is not valid@email$com");
Kakashi,
15
Wydaje się, że wiele problemów polega na tym, że MailAddress próbuje również parsować DisplayName, więc „single [email protected]” analizuje na DisplayName „single” i adres „[email protected]”. Rozwiązaniem tego jest: powrót (adres = adres == e-mail);
Stuart
18
Lubię to; Nie uznaję tego za bardziej restrykcyjny niż rzeczywista specyfikacja. Fałszywe negatywy są znacznie gorsze niż fałszywe pozytywy („co masz na myśli, że mój adres e-mail jest nieprawidłowy? ”)
Casey
242

To stare pytanie, ale na wszystkie odpowiedzi, które znalazłem na SO, w tym nowsze, odpowiedziały podobnie do tego. Jednak w .Net 4.5 / MVC 4 możesz dodać weryfikację adresu e-mail do formularza, dodając adnotację [EmailAddress] z System.ComponentModel.DataAnnotations, więc zastanawiałem się, dlaczego nie mogłem po prostu korzystać z wbudowanej funkcjonalności. Netto w ogóle.

To wydaje się działać i wydaje mi się dość eleganckie:

using System.ComponentModel.DataAnnotations;

class ValidateSomeEmails
{
    static void Main(string[] args)
    {
        var foo = new EmailAddressAttribute();
        bool bar;
        bar = foo.IsValid("[email protected]");         //true
        bar = foo.IsValid("[email protected]");       //true
        bar = foo.IsValid("[email protected]");     //true
        bar = foo.IsValid("[email protected]");      //true

        bar = foo.IsValid("fdsa");                          //false
        bar = foo.IsValid("fdsa@");                         //false
        bar = foo.IsValid("fdsa@fdsa");                     //false
        bar = foo.IsValid("fdsa@fdsa.");                    //false

        //one-liner
        if (new EmailAddressAttribute().IsValid("[email protected]"))
            bar = true;    
    }
}
imjosh
źródło
4
Fajnie, choć to rozczarowujące, że stwardnienie rozsiane nie może zgodzić się z ich własną dokumentacją . To odrzuca [email protected]
Casey
13
Zauważ, że EmailAddressAttributejest mniej liberalny niż System.Net.Mail.MailAddress- na przykład, MailAddressakceptuje adres TLD. Pamiętaj o tym, jeśli chcesz być jak najbardziej tolerancyjny.
Aaroninus
5
@ Koło zębate: jeśli odpowiedź leży gdzieś w komentarzach, prawdopodobnie powinna zostać dodana do głównej części odpowiedzi.
hofnarwillie
6
@hofnarwillie: jest w głównej części, ale komentarze są rozbudowane. Jeśli Twoim celem jest nie gniewanie użytkowników, weryfikacja nie powinna być bardziej restrykcyjna niż specyfikacja. Jedynym sposobem, aby naprawdę sprawdzić, czy e-mail jest prawidłowy, jest wysłanie wiadomości testowej.
Koło zębate
4
Uwaga: foo.IsValid(null);zwroty true.
urig
62

Używam tej metody pojedynczej wkładki, która działa dla mnie-

using System.ComponentModel.DataAnnotations;
public bool IsValidEmail(string source)
{
    return new EmailAddressAttribute().IsValid(source);
}

Zgodnie z komentarzami „nie powiedzie się”, jeśli source(adres e-mail) ma wartość NULL.

public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);
Manik Arora
źródło
1
To mi nie działa; Rozumiem: „Adnotacje danych” nie istnieją ... brakuje odniesienia do zestawu? ” Które odniesienie muszę dodać?
B. Clay Shannon,
Zwróci wartość true, jeśli źródło ma wartość null. Patrz msdn.microsoft.com/en-us/library/hh192424 „prawda, jeśli określona wartość jest poprawna lub zerowa; w przeciwnym razie fałsz”.
jao
2
Lepsza wersja:public static Boolean IsValidMailAddress(this String pThis) => pThis == null ? false : new EmailAddressAttribute().IsValid(pThis);
Sebastian Hofmann,
7
Lub jeszcze lepiej:public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);
Patrik Melander
1
Nie sądzę, aby ta metoda rozszerzenia po cichu falsezwracała ciągi zerowe. Dlatego proponuję (nawet lepiej) ++ lepszą wersję: public static bool IsValidEmailAddress(this string address) => new EmailAddressAttribute().IsValid(address ?? throw new ArgumentNullException());. Pójdę teraz i znajdę Reformowany Kościół jeszcze lepszych wersjonistów.
Marc.2377
41

.net 4.5 dodał System.ComponentModel.DataAnnotations.EmailAddressAttribute

Możesz przeglądać źródło EmailAddressAttribute , jest to Regex, którego używa wewnętrznie:

const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";
Chad Grant
źródło
2
Niestety EmaillAddressAttribute pozwala Ñ, który nie jest prawidłowym znakiem dla wiadomości e
BZ
16
@BZ Tak to jest. Jak myślisz, dlaczego tak nie jest?
Casey
@Chad Grant: To jest wersja C #. Czy możesz podać VB.Net? Ponieważ to pozwoli uniknąć znaków takich jak \\ do \ lub możesz podać ciąg znaków dosłownie.
Nikhil Agrawal,
3
Działa to, ale nie zapominaj, RegexOptions.IgnoreCaseponieważ ten wzór nie dopuszcza wyraźnie wielkich liter!
Chris
1
Zauważ, że Regex jest bardzo celowy: „Ten atrybut zapewnia sprawdzanie poprawności wiadomości e-mail po stronie serwera równoważne sprawdzaniu poprawności jquery, a zatem ma takie samo wyrażenie regularne”.
Ohad Schneider,
38

Wziąłem odpowiedź Phila z nr 1 i stworzyłem tę klasę. Nazwij to tak:bool isValid = Validator.EmailIsValid(emailString);

Oto klasa:

using System.Text.RegularExpressions;

public static class Validator
{

    static Regex ValidEmailRegex = CreateValidEmailRegex();

    /// <summary>
    /// Taken from http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx
    /// </summary>
    /// <returns></returns>
    private static Regex CreateValidEmailRegex()
    {
        string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

        return new Regex(validEmailPattern, RegexOptions.IgnoreCase);
    }

    internal static bool EmailIsValid(string emailAddress)
    {
        bool isValid = ValidEmailRegex.IsMatch(emailAddress);

        return isValid;
    }
}
David Silva Smith
źródło
5
Tylko mały, ale użyłbym: return (! String.IsNullOrEmpty (emailAddress)) && ValidEmailRegex.IsMatch (emailAddress);
Marc
To tylko horror :)
Alexandru Dicu,
31

Osobiście powiedziałbym, że powinieneś tylko upewnić się, że jest tam symbol @, ewentualnie z. postać. Istnieje wiele wyrażeń regularnych, których można użyć z różną poprawnością, ale myślę, że większość z nich pomija prawidłowe adresy e-mail lub przepuszcza nieprawidłowe. Jeśli ludzie chcą podać fałszywy adres e-mail, podadzą fałszywy adres. Jeśli musisz sprawdzić, czy adres e-mail jest prawidłowy i czy dana osoba ma kontrolę nad tym adresem e-mail, musisz wysłać mu wiadomość e-mail ze specjalnym kodowanym łączem, aby mogli zweryfikować, czy rzeczywiście jest to prawdziwy adres.

Kibee
źródło
6
Osobiście uważam, że powinieneś zrobić trochę więcej weryfikacji. Ktoś musi wypróbować adres e-mail Bobby Table lub gorzej.
Luke Quinane,
31
Co jest nie tak z adresem e-mail tabeli bobby, jeśli używasz przygotowanych wyciągów. Mówimy o prawidłowych adresach e-mail, a nie o innych rzeczach, które nie mają nic wspólnego z tym, co stanowi prawidłowy adres e-mail, na przykład o tym, jak poprawnie wykonywać zapytania SQL, aby nie występowały problemy z iniekcją SQL.
Kibbee
Myślę, że nie wiesz, co ktoś tam umieści, ale złośliwa osoba wie, że wartość może ostatecznie zostać wprowadzona do twojego systemu pocztowego. Wolałbym raczej zagłębić się w obronę i być bardziej surowym.
Luke Quinane
10
To dotyczy systemu pocztowego. Nie odrzuciłbym idealnie poprawnych adresów e-mail tylko dlatego, że może to być problem z bezpieczeństwem w innym systemie. Jeśli wszystkie potrzeby serwera e-mail to źle sformułowany adres e-mail, który może powodować problemy z bezpieczeństwem, prawdopodobnie powinieneś przełączyć się na inny serwer.
Kibbee
4
Głęboka obrona działa tylko wtedy, gdy każdy poziom twojej cebuli bezpieczeństwa nie jest zepsuty. Jedna zgniła warstwa oznacza, że ​​psujesz całą cebulę. Odrzucenie „[email protected]”, ponieważ chcesz bronić się przed lukami w kodowaniu µ-law firmy Sun, nie ma sensu, prawda? Nie śmiej się, to mi się przydarzyło. Komentuję to dlatego, że Medicare Australia nie zezwala na adresy „.au”, tylko „.com”. Przeczytaj także Mark Swanson, „Jak nie sprawdzać poprawności wiadomości e-mail”, mdswanson.com/blog/2013/10/14/…
ManicDee
17

Myślę, że najlepszy sposób jest następujący:

    public static bool EmailIsValid(string email)
    {
        string expression = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

        if (Regex.IsMatch(email, expression))
        {
            if (Regex.Replace(email, expression, string.Empty).Length == 0)
            {
                return true;
            }
        }
        return false;
    }

Możesz mieć tę funkcję statyczną w klasie ogólnej.

Poyson 1
źródło
Ta odpowiedź nie akceptuje adresu z TLD w części domeny.
Simone
15

Krótki i dokładny kod

string Email = txtEmail.Text;
if (Email.IsValidEmail())
{
   //use code here 
}

public static bool IsValidEmail(this string email)
{
  string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";    
  var regex = new Regex(pattern, RegexOptions.IgnoreCase);    
  return regex.IsMatch(email);
}
Naveen
źródło
2
Dzięki za rozwiązanie
Jack Gajanan
Musiałem zmienić publiczny statyczny bool IsValidEmail (ten ciąg e-mail) na publiczny statyczny bool IsValidEmail (ciąg e-mail), aby uniknąć TO: stackoverflow.com/questions/10412233/...
Goner Doug
@Goner Doug, ta funkcjonalność będzie działać w ten sposób. (Bool flag = EmailAddress.IsValidEmail ())
Naveen 30.04.19
2
„TO” musiało zostać usunięte, aby uniknąć problemów z kompilatorem po dodaniu do mojego formularza.
Goner Doug
@ Goner Doug, Jego funkcjonalność będzie działać w ten sposób. ciąg email = "[email protected]"; if (email.IsValidEmail ()) {return false; } else {return true;}
Naveen
14

Najbardziej eleganckim sposobem jest użycie metod wbudowanych w .Net.

Te metody:

  • Są wypróbowane i przetestowane. Te metody są stosowane w moich własnych profesjonalnych projektach.

  • Używaj wyrażeń regularnych wewnętrznie, które są niezawodne i szybkie.

  • Wykonane przez Microsoft dla C #. Nie ma potrzeby wymyślania nowego koła.

  • Zwraca wynik bool. Prawda oznacza, że ​​adres e-mail jest prawidłowy.

Dla użytkowników .Net 4.5 i nowszych

Dodaj to odniesienie do swojego projektu:

System.ComponentModel.DataAnnotations

Teraz możesz użyć następującego kodu:

(new EmailAddressAttribute().IsValid("[email protected]"));

Przykład zastosowania

Oto kilka metod deklarowania:

protected List<string> GetRecipients() // Gets recipients from TextBox named `TxtRecipients`
{
    List<string> MethodResult = null;

    try
    {
        List<string> Recipients = TxtRecipients.Text.Replace(",",";").Replace(" ", "").Split(';').ToList();

        List<string> RecipientsCleaned = new List<string>();

        foreach (string Recipient in RecipientsCleaned)
        {
            if (!String.IsNullOrWhiteSpace(Recipient))
            {
                RecipientsNoBlanks.Add(Recipient);

            }

        }

        MethodResult = RecipientsNoBlanks;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();
    }

    return MethodResult;

}


public static bool IsValidEmailAddresses(List<string> recipients)
{
    List<string> InvalidAddresses = GetInvalidEmailAddresses(recipients);

    return InvalidAddresses != null && InvalidAddresses.Count == 0;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!(new EmailAddressAttribute().IsValid(Recipient)) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

... i kod pokazujący je w akcji:

List<string> Recipients = GetRecipients();

bool IsValidEmailAddresses = IsValidEmailAddresses(Recipients);

if (IsValidEmailAddresses)
{
    //Emails are valid. Your code here

}
else
{
    StringBuilder sb = new StringBuilder();

    sb.Append("The following addresses are invalid:");

    List<string> InvalidEmails = GetInvalidEmailAddresses(Recipients);

    foreach (string InvalidEmail in InvalidEmails)
    {
        sb.Append("\n" + InvalidEmail);

    }

    MessageBox.Show(sb.ToString());

}

Ponadto ten przykład:

  • Wykracza poza specyfikację, ponieważ pojedynczy ciąg znaków zawiera 0, jeden lub wiele adresów e-mail sperowanych przez średnik ; .
  • Wyraźnie pokazuje, jak korzystać z metody IsValid obiektu EmailAddressAttribute.

Alternatywnie, dla użytkowników wersji .Net mniejszej niż 4.5

W sytuacjach, w których .Net 4.5 nie jest dostępny, używam następującego rozwiązania:

W szczególności używam:

public static bool IsValidEmailAddress(string emailAddress)
{
    bool MethodResult = false;

    try
    {
        MailAddress m = new MailAddress(emailAddress);

        MethodResult = m.Address == emailAddress;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!IsValidEmail(Recipient) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}
WonderWorker
źródło
1
@ThomasAyoub Nie widziałem odpowiedzi EmailAddressAttribute, i nie ma odpowiedzi, która używa nowej MailAddress () z kontrolą wejścia == .Address, więc uważam, że jest bardzo przydatna. Bez czytania komentarzy zaakceptowana odpowiedź jest dość błędna. nowy MailAddress („Foobar [email protected]”) to potwierdza.
Jan
@Jan fwiw, Manik pokonał Knickerlessa w EmailAddressAttributeniecałe cztery miesiące, choć ten chwyta nullproblem.
ruffin
7

Szczerze mówiąc, w kodzie produkcyjnym najlepiej sprawdzać @symbol.

Nigdy nie jestem w miejscu, aby całkowicie sprawdzać poprawność wiadomości e-mail. Wiesz, jak widzę, czy to naprawdę było ważne? Jeśli został wysłany. Jeśli nie, to źle, jeśli tak, życie jest dobre. To wszystko, co muszę wiedzieć.

Południe jedwabiu
źródło
6

Uważam, że ten regex stanowi dobry kompromis między sprawdzaniem czegoś więcej niż znaku @ i akceptowaniem dziwnych przypadków krawędzi:

^[^@\s]+@[^@\s]+(\.[^@\s]+)+$

Przynajmniej sprawi, że umieścisz coś wokół znaku @ i umieścisz przynajmniej normalnie wyglądającą domenę.

Matthew Lock
źródło
Wymyśliłem ten sam regex;) Jednak dopuszcza to nieprawidłowe postacie
Stefan
Ta odpowiedź nie akceptuje TLD w części domeny.
Simone
@ Simone prawdopodobnie nikt nie ma adresów e-mail z TLD w części domeny, chociaż w praktyce: serverfault.com/a/721929/167961 Uwaga w komentarzach może być zabronione w dzisiejszych czasach
Matthew Lock
@MatthewLock Czy może to być adres intranetowy? Jak bob@companyinternal?
Simone
@Simone, czy ktoś w rzeczywistości faktycznie korzysta z tego programu?
Matthew Lock
4

Sprawdzanie poprawności adresu e-mail nie jest tak proste, jak mogłoby się wydawać. W rzeczywistości teoretycznie niemożliwe jest pełne sprawdzenie adresu e-mail za pomocą wyrażenia regularnego.

Sprawdź mój post na blogu , aby uzyskać dyskusję na ten temat i implementację F # przy użyciu FParsec. [/ shameless_plug]

Mauricio Scheffer
źródło
1
Podobała mi się lista alternatywnych podejść; bardzo interesujące.
Luke Quinane,
1
Interesujący artykuł. Ale tak na poważnie, kto umieszcza komentarze i zagnieżdża je w adresach e-mail?
Matthew Lock
3
@matthew Nie wiem, dlaczego IETF nawet na to zezwala, ale jest to możliwe , więc należy to dokładnie przeanalizować.
Mauricio Scheffer,
4

Oto moja odpowiedź - rozwiązanie Phila zawodzi w przypadku domen jednoliterowych, takich jak „ktoś@q.com”. Wierzcie lub nie, to jest używane =) (na przykład idzie do centurylink).

Odpowiedź Phila będzie działała tylko ze standardem PCRE ... więc C # to zajmie, ale javascript będzie bombardował. Jest zbyt skomplikowany dla javascript. Nie można więc użyć rozwiązania Phila do sprawdzania poprawności atrybutów mvc.

Oto moje wyrażenie regularne. Będzie działał ładnie z atrybutami sprawdzania poprawności MVC.
- Wszystko przed @ jest uproszczone, aby przynajmniej javascript działał. W porządku, rozluźniam sprawdzanie poprawności, o ile serwer Exchange nie daje mi wersji 5.1.3. - Wszystko po @ jest rozwiązaniem Phila zmodyfikowanym dla domen jednoliterowych.

public const string EmailPattern =
        @"^\s*[\w\-\+_']+(\.[\w\-\+_']+)*\@[A-Za-z0-9]([\w\.-]*[A-Za-z0-9])?\.[A-Za-z][A-Za-z\.]*[A-Za-z]$";

Dla osób sugerujących użycie system.net.mail MailMessage () jest to DROGA do elastyczności. Jasne, C # zaakceptuje wiadomość e-mail, ale następnie serwer wymiany bombarduje błędem czasu wykonania 5.1.3, gdy tylko spróbujesz wysłać wiadomość e-mail.

Ralph N.
źródło
to wydaje się być najlepszą najbardziej przemyślaną / rozsądną / rzeczywistą odpowiedzią, dzięki Ralph!
Fattie
to najlepsza jak dotąd odpowiedź! Nie mogę uwierzyć, że złe rozwiązanie, które akceptuje basket@balljako prawidłowy adres e-mail, uzyskało poprawną odpowiedź, a także wszystkie te pozytywne opinie. W każdym razie dzięki!
disasterkid
Dzięki, to najlepsze rozwiązanie i należy przyjąć odpowiedź.
Bat_Programmer
3

Jeśli naprawdę i mam na myśli naprawdę chcesz wiedzieć, czy adres e-mail jest prawidłowy ... poproś wymiennik poczty, aby to udowodnił, nie wymaga wyrażenia regularnego. Na żądanie mogę podać kod.

Ogólne kroki są następujące: 1. Czy adres e-mail ma część nazwy domeny? (indeks @> 0) 2. za pomocą zapytania DNS zapytaj, czy domena ma wymiennik poczty 3. otwórz połączenie TCP z wymiennikiem poczty 4. używając protokołu smtp otwórz wiadomość do serwera, używając adresu e-mail jako odbiorcy 5. przeanalizować odpowiedź serwera. 6. zamknij wiadomość, jeśli dotarłeś tak daleko, wszystko jest dobrze.

Jest to, jak możesz sobie wyobrazić, bardzo kosztowne pod względem czasu i opiera się na smtp, ale działa.

Joe Caffeine
źródło
Czy stworzyłeś podróbki, kody pośredniczące i / lub makiety dla tych interfejsów?
Mark A
1
To nie zadziała. Protokół smtp do weryfikacji adresu e-mail był DŁUGO przestarzały / nieużywany. Włączanie tej funkcji na serwerach pocztowych jest uważane za złą praktykę, ponieważ spamerzy używają tej funkcji.
Chad Grant
Dotrzymam twojej sugestii do punktu 2. Znacznie bardziej przyszłościowy niż sprawdzanie znanego wzorca nazwy domeny.
Simone
Nitpicking, ale zdefiniuj „ma wymiennik poczty” ? Jeśli nie istnieją żadne rekordy MX, SMTP powinien wrócić do rekordu A / AAAA, zgodnie z RFC2821 / 5321. Jeśli rekord MX istnieje, nadal może nie oznaczać, że istnieje wymiennik poczty (RFC7505). Naprawdę jedynym sposobem jest wysłanie im wiadomości z linkiem wezwania do działania i poczekanie, aż odpowiedzą ...
jimbobmcgee
2

Ogólnie rzecz biorąc, wyrażenie regularne do sprawdzania adresów e-mail nie jest łatwe do wymyślenia; w chwili pisania tego tekstu składnia adresu e-mail musi być zgodna ze stosunkowo dużą liczbą standardów, a implementacja wszystkich z nich w wyrażeniu regularnym jest praktycznie niewykonalna!

Gorąco polecam do wypróbowania naszego EmailVerify.NET , dojrzałą biblioteki .NET, który może zatwierdzić następujące adresy e-mail wszystkich aktualnymi standardami IETF (RFC 1123, RFC 2821, RFC 2822, RFC 3696, RFC 4291, RFC 5321 i RFC 5322) , testuje powiązane rekordy DNS, sprawdza, czy docelowe skrzynki pocztowe mogą akceptować wiadomości, a nawet może stwierdzić, czy dany adres jest jednorazowy, czy nie.

Oświadczenie: Jestem głównym programistą tego komponentu.

Efran Cobisi
źródło
Imponujący! „Następnie próbuje skontaktować się z wymiennikiem poczty odpowiedzialnym za podany adres e-mail i rozpoczyna fałszywe okno dialogowe SMTP z tym serwerem, emulując prawdziwy serwer poczty. W ten sposób serwer może obsłużyć wiadomości e-mail dotyczące adresu. Wiele serwerów SMTP faktycznie dać fałszywie pozytywne odpowiedzi jako ochronę przed spamerami: aby rozwiązać ten problem, EmailVerify dla .NET w końcu próbuje wielokrotnie zapytać docelowy wymiennik poczty przy użyciu różnych sfabrykowanych adresów. ”
Matthew Lock
Dzięki, @MatthewLock;)
Efran Cobisi
Fajnie, ale widzę tylko płatne wersje. Jakieś plany dotyczące wydania społeczności / OpenSource?
Ohad Schneider,
1
@OhadSchneider Tak: oferujemy bezpłatną wersję naszej technologii sprawdzania poprawności wiadomości e-mail za pośrednictwem Verifalia, naszej usługi weryfikacji poczty e-mail SaaS . Verifalia jest dostarczana z darmowymi i otwartymi pakietami SDK dla głównych platform programistycznych, w tym .NET .
Efran Cobisi,
2
For the simple email like goerge@xxx.com, below code is sufficient. 

 public static bool ValidateEmail(string email)
        {
            System.Text.RegularExpressions.Regex emailRegex = new System.Text.RegularExpressions.Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
            System.Text.RegularExpressions.Match emailMatch = emailRegex.Match(email);
            return emailMatch.Success;
        }
użytkownik2211290
źródło
Nie można zweryfikować [email protected] jako prawidłowego adresu e-mail.
Ray Cheng
2

W przypadku korzystania z FluentValidation możesz napisać coś tak prostego:

public cass User
{
    public string Email { get; set; }
}

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Email).EmailAddress().WithMessage("The text entered is not a valid email address.");
    }
}

// Validates an user. 
var validationResult = new UserValidator().Validate(new User { Email = "açflkdj" });

// This will return false, since the user email is not valid.
bool userIsValid = validationResult.IsValid;
Ulisses Alves
źródło
2

mała modyfikacja odpowiedzi na @Cogwheel

public static bool IsValidEmail(this string email)
{
  // skip the exception & return early if possible
  if (email.IndexOf("@") <= 0) return false;

  try
  {
    var address = new MailAddress(email);
    return address.Address == email;
  }
  catch
  {
    return false;
  }
}
czekaj na to
źródło
Wydaje się, że to nie pomaga ... Console.WriteLine(MailAddress("asdf@asdf.").Address);wyświetla „asdf @ asdf.”, Co nie jest poprawne.
Langdon
Wydaje się, że .net ma własną definicję poprawności. powiązana dyskusja
waitforit
2

Istnieje tutaj wiele silnych odpowiedzi. Zalecam jednak cofnąć się o krok. @Cogwheel odpowiada na pytanie https://stackoverflow.com/a/1374644/388267 . Niemniej jednak może być kosztowne w scenariuszu weryfikacji zbiorczej, jeśli wiele z weryfikowanych adresów e-mail jest nieprawidłowych. Sugeruję, abyśmy zastosowali odrobinę logiki, zanim wejdziemy do jego bloku try-catch. Wiem, że poniższy kod można napisać przy użyciu RegEx, ale zrozumienie go przez nowych programistów może być kosztowne. To jest moja wartość podwójna:

    public static bool IsEmail(this string input)
    {
        if (string.IsNullOrWhiteSpace(input)) return false;

        // MUST CONTAIN ONE AND ONLY ONE @
        var atCount = input.Count(c => c == '@');
        if (atCount != 1) return false;

        // MUST CONTAIN PERIOD
        if (!input.Contains(".")) return false;

        // @ MUST OCCUR BEFORE LAST PERIOD
        var indexOfAt = input.IndexOf("@", StringComparison.Ordinal);
        var lastIndexOfPeriod = input.LastIndexOf(".", StringComparison.Ordinal);
        var atBeforeLastPeriod = lastIndexOfPeriod > indexOfAt;
        if (!atBeforeLastPeriod) return false;

        // CODE FROM COGWHEEL'S ANSWER: https://stackoverflow.com/a/1374644/388267 
        try
        {
            var addr = new System.Net.Mail.MailAddress(input);
            return addr.Address == input;
        }
        catch
        {
            return false;
        }
    }
CarneyCode
źródło
2

Najbardziej głosowana odpowiedź z @Cogwheel jest najlepszą odpowiedzią, ale próbowałem zaimplementować trim()metodę string, aby odciąć wszystkie białe znaki użytkownika od początku do końca. Sprawdź poniższy kod w celu uzyskania pełnego przykładu-

bool IsValidEmail(string email)
{
    try
    {
        email = email.Trim();
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == email;
    }
    catch
    {
        return false;
    }
}
Liakat
źródło
Istnieje ryzyko, że sprawdzasz inny adres e-mail niż źródło, co pozwala myśleć, że możesz wysyłać pocztę na (w tym przypadku) nieokreśloną wersję określonego adresu e-mail. Lepszym podejściem byłoby stworzenie oddzielnej metody SanitizeEmail(string email), wykorzystując wyniki tej metody do sprawdzenia poprawności i wysłania wiadomości e-mail na adres.
Marco de Zeeuw
1
private static bool IsValidEmail(string emailAddress)
{
    const string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
                                     + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
                                     + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

    return new Regex(validEmailPattern, RegexOptions.IgnoreCase).IsMatch(emailAddress);
}
ErwanLent
źródło
1

Sprawdź, czy ciąg wiadomości e-mail ma prawidłowy lub niewłaściwy format, wykonując System.Text.RegularExpressions:

    public static bool IsValidEmailId(string InputEmail)
    {
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
        Match match = regex.Match(InputEmail);
        if (match.Success)
            return true;
        else
            return false;
    }

    protected void Email_TextChanged(object sender, EventArgs e)
    {
        String UserEmail = Email.Text;
        if (IsValidEmailId(UserEmail))
        {
            Label4.Text = "This email is correct formate";
        }
        else
        {
            Label4.Text = "This email isn't correct formate";
        }
    }
rktuxyn
źródło
1

/ Korzystanie z wewnętrznego regexu używanego do tworzenia „nowego EmailAddressAttribute ();”; komponent w .Net4.5 >>> przy użyciu System.ComponentModel.DataAnnotations; // Aby zweryfikować adres e-mail ...... Testowany i działa.

public bool IsEmail(string email)
{
    if (String.IsNullOrEmpty(email))
    {   return false;  }
    try
    {
        Regex _regex = new Regex("^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])" +
                "+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)" +
                "((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|" +
                "[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\u" +
                "FDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|" +
                "(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|" +
                "[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900" +
                "-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFF" +
                "EF])))\\.?$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
        return _regex.IsMatch(email);
    }
    catch (RegexMatchTimeoutException)
    {
        return false;
    }
}

Możesz także użyć tego:

http://msdn.microsoft.com/en-us/library/01escwtf(v=vs.110).aspx

Aina Ademola C.
źródło
mówi prawdę dla tego e-maila: „[email protected]ö” i zgłasza błąd w mandrill api
MonsterMMORPG
1
Po pierwsze, adres e-mail jest poprawny wrt [email protected] lub [email protected] .... Wiadomość e-mail ma cały prawidłowy ciąg znaków i kryterium, z wyjątkiem ostatniego znaku „ö” i można łatwo dodać prosty warunek, aby zweryfikować taki znak . Po drugie, nie jestem pewien co do tego błędu mandrill api, możesz chcieć zweryfikować swoją metodę użycia bcos Użyłem tej walidacji w innym środowisku / api i było dla mnie dobre.
Aina Ademola C
1

W skrócie streściłem odpowiedź Poyson 1:

public static bool IsValidEmailAddress(string candidateEmailAddr)
{
    string regexExpresion = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
    return (Regex.IsMatch(candidateEmailAddr, regexExpresion)) && 
           (Regex.Replace(candidateEmailAddr, regexExpresion, string.Empty).Length == 0);
}
B. Clay Shannon
źródło
1

Prosty sposób identyfikacji adresu e-mail jest prawidłowy lub nie.

public static bool EmailIsValid(string email)
{
        return Regex.IsMatch(email, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
}
Amit Gorvadiya
źródło
1

Występuje problem kulturowy w wyrażeniach regularnych w języku C # zamiast w js. Musimy więc użyć wyrażenia regularnego w trybie USA do sprawdzania poczty e-mail. Jeśli nie używasz trybu ECMAScript, twoje znaki specjalne w języku oznaczają w AZ za pomocą wyrażenia regularnego.

Regex.IsMatch(email, @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9_\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", RegexOptions.ECMAScript)
mkysoft
źródło
1

Skończyło się na tym wyrażeniu regularnym, ponieważ z powodzeniem sprawdza poprawność przecinków, komentarzy, znaków Unicode i adresów domen IP (v4).

Prawidłowe adresy to:

„” @ example.org

(comment)[email protected]

тест@example.org

ტესტი @ example.org

test @ [192.168.1.1]

 public const string REGEX_EMAIL = @"^(((\([\w!#$%&'*+\/=?^_`{|}~-]*\))?[^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))(\([\w!#$%&'*+\/=?^_`{|}~-]*\))?@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$";
d.popov
źródło
1

Prosty bez użycia Regex (co nie podoba mi się ze względu na słabą czytelność):

bool IsValidEmail(string email)
{
    string emailTrimed = email.Trim();

    if (!string.IsNullOrEmpty(emailTrimed))
    {
        bool hasWhitespace = emailTrimed.Contains(" ");

        int indexOfAtSign = emailTrimed.LastIndexOf('@');

        if (indexOfAtSign > 0 && !hasWhitespace)
        {
            string afterAtSign = emailTrimed.Substring(indexOfAtSign + 1);

            int indexOfDotAfterAtSign = afterAtSign.LastIndexOf('.');

            if (indexOfDotAfterAtSign > 0 && afterAtSign.Substring(indexOfDotAfterAtSign).Length > 1)
                return true;
        }
    }

    return false;
}

Przykłady:

Ma być prosty i dlatego nie zajmuje się rzadkimi przypadkami, takimi jak wiadomości e-mail z domenami w nawiasach kwadratowych, które zawierają spacje (zwykle dozwolone), wiadomości e-mail z adresami IPv6 itp.

aBertrand
źródło
1

Oto odpowiedź na twoje pytanie do sprawdzenia.

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

public class RegexUtilities
{    
   public bool IsValidEmail(string strIn)
   {
       if (String.IsNullOrEmpty(strIn))
       {
          return false;

       }

       // Use IdnMapping class to convert Unicode domain names.

       try 
       {
          strIn = Regex.Replace(strIn, @"(@)(.+)$", this.DomainMapper, RegexOptions.None, TimeSpan.FromMilliseconds(200));

       }
       catch (RegexMatchTimeoutException) 
       {
           return false;

       }

       if (invalid)
       {
           return false;

       }

       // Return true if strIn is in valid e-mail format.    

       try 
       {
          return Regex.IsMatch(strIn, @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|       [-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));

       }
       catch (RegexMatchTimeoutException) 
       {
          return false;

       }

   }


   private string DomainMapper(Match match)
   {
      // IdnMapping class with default property values.

      IdnMapping idn = new IdnMapping();

      string domainName = match.Groups[2].Value;

      try 
      {
         domainName = idn.GetAscii(domainName);

      }
      catch (ArgumentException) 
      {
         invalid = true;

      }

      return match.Groups[1].Value + domainName;

   }

}
Parsa Karami
źródło
1

Na podstawie odpowiedzi @Cogwheel chcę udostępnić zmodyfikowane rozwiązanie, które działa dla SSIS i „Składnika skryptu”:

  1. Umieść „Składnik skryptu” w łączu przepływu danych, a następnie otwórz go.
  2. W sekcji „Kolumny wejściowe” ustaw pole zawierające adresy e-mail na „ReadWrite” (w przykładzie „fieldName”).
  3. Wróć do sekcji „Skrypt” i kliknij „Edytuj skrypt”. Następnie musisz poczekać, aż kod się otworzy.
  4. Umieść ten kod we właściwej metodzie:

    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        string email = Row.fieldName;
    
        try
        {
            System.Net.Mail.MailAddress addr = new System.Net.Mail.MailAddress(email);
            Row.fieldName= addr.Address.ToString();
        }
        catch
        {
            Row.fieldName = "WRONGADDRESS";
        }
    }

Następnie możesz użyć podziału warunkowego, aby odfiltrować wszystkie nieprawidłowe rekordy lub cokolwiek chcesz zrobić.

użytkownik3772108
źródło