Jakie są najlepsze praktyki dotyczące sprawdzania poprawności adresów e-mail w systemie iOS 2.0

167

Jaki jest najczystszy sposób weryfikacji adresu e-mail wprowadzanego przez użytkownika w systemie iOS 2.0?

UWAGA : Jest to pytanie historyczne, które jest specyficzne dla iOS 2.0 i ze względu na jego wiek i liczbę powiązanych z nim pytań nie można go wycofać i NIE WOLNO go zmieniać na pytanie „nowoczesne”.

Marcus S. Zarra
źródło
Szukam roztworu kakao. Rozumiem ważność wiadomości e-mail i zasady dotyczące weryfikacji wiadomości e-mail. Jednak ponieważ wyrażenie RegEx nie jest łatwo dostępne w Cocoa Touch, szukam rozwiązania Cocoa Touch do walidacji. To nie jest lista zasad dotyczących walidacji.
Marcus S. Zarra
Jak dotąd najlepszą sugestią dotyczącą kodu, jaką znalazłem, jest użycie RegExKitLite i wyrażeń regularnych. Na szczęście jest to mniej bolesne niż się wydaje.
Marcus S. Zarra
Zobacz komentarze poniżej dotyczące używania NSRegularExpression dla aplikacji, które nie obsługują systemu operacyjnego <4.0.
od
1
Ponieważ wydaje się, że jest to kanoniczne pytanie dotyczące weryfikacji adresu e-mail, sensowne jest aktualizowanie poprawionych odpowiedzi w miarę dojrzewania systemu iOS. Mając to na uwadze, dodałem odpowiedź, która wykorzystuje iOS NSDataDetectordo weryfikacji adresów e-mail: stackoverflow.com/a/23547905/257550
memmons
2
To pytanie wydaje się nie na temat, ponieważ dotyczy iOS 2.0, który został wycofany lata temu.
Nathan Eror

Odpowiedzi:

354

Odpowiedź na temat używania wyrażeń regularnych do sprawdzania poprawności adresu e-mail wyjaśnia szczegółowo, że gramatyka określona w dokumencie RFC 5322 jest zbyt skomplikowana dla prymitywnych wyrażeń regularnych.

Polecam prawdziwe podejście do parsera, takie jak MKEmailAddress .

Jako szybkie rozwiązanie wyrażeń regularnych zobacz tę modyfikację DHValidation :

- (BOOL) validateEmail: (NSString *) candidate {
    NSString *emailRegex =
@"(?:[a-z0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&'*+/=?\\^_`{|}"
@"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
@"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
@"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
@"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
@"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
@"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"; 
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES[c] %@", emailRegex]; 

    return [emailTest evaluateWithObject:candidate];
}
catlan
źródło
9
Świetnie, ale nie działa na OS <3.0, ponieważ NSPredicate nie jest dostępny.
Felixyz
4
Miły. Wszyscy zapominają, że NSPredicate może uruchamiać wyrażenia regularne.
Rog,
5
To jest jedno bardzo złe wyrażenie regularne. Na przykład zakończy się niepowodzeniem u osób korzystających z domeny głównej .museum. Zapoznaj się z tym artykułem: linuxjournal.com/article/9585
Jonny
18
Na cocoawithlove.com/2009/06/ ... jest bardziej kompletne wyrażenie regularne, którego można użyć zamiast tego prostego.
Tomas Andrle
12
Oto bardzo naiwne, ale liberalne wyrażenie regularne e-mail jako ciąg znaków Cocoa: @"[^@]+@[^.@]+(\\.[^.@]+)+"Jeśli chcesz zweryfikować adres e-mail, wyślij na niego wiadomość i sprawdź, czy się powiedzie. Nigdy nie zweryfikujesz tego z żadnym poziomem dokładności za pomocą samego wyrażenia regularnego, więc najlepiej nie wkurzać użytkowników i tracić rejestracji z powodu niepotrzebnie ścisłego wyrażenia regularnego.
Sami Samhuri
20

Przeczytaj RFC. Prawie każdy, kto myśli, że wie, jak przeanalizować / wyczyścić / zweryfikować adres e-mail, jest w błędzie.

http://tools.ietf.org/html/rfc2822 Sekcja 3.4.1 jest bardzo przydatna. Ogłoszenie

dtext = NO-WS-CTL /; Kontrolki bez spacji

                        % d33-90 /; Reszta US-ASCII
                        % d94-126; znaki bez "[",
                                        ; „]” lub „\”

Tak, to znaczy, że +, 'itd. Są legalne.

Trey
źródło
Aktualne na maj 2016: RFC5322, sekcja 3.4.1
leanne
17

Najlepszym rozwiązaniem, jakie do tej pory znalazłem (i tym, z którym się zdecydowałem) jest dodanie RegexKitLite do projektu, który daje dostęp do wyrażeń regularnych poprzez NSString Categories.

Dodanie do projektu jest dość bezbolesne, a po utworzeniu dowolna logika weryfikacji wiadomości e-mail z wyrażeniami regularnymi będzie działać.

Marcus S. Zarra
źródło
5
NSPredicate może wykonywać RegEx bez dodawania dodatkowych bibliotek do projektu.
BadPirate
10
To pytanie od kwietnia 2009 było zanim NSPredicate istniało na iOS.
Marcus S. Zarra
7
Ponownie, NSRegularExpression NIE ISTNIEJE w iOS 2.0, kiedy zadano to pytanie.
Marcus S. Zarra
9
@Marcus, celem Stack Overflow nie jest prowadzenie historycznego zapisu tego, jak poszczególne problemy zostały rozwiązane w przeszłości. To powiedziawszy, zredagowałem twoje pytanie, aby podkreślić kąt kompatybilności 2.0.
benzado
2
Przeczytaj tytuł, dotyczy iOS 2.0, którego rozwiązanie Catlan nie istniało.
Marcus S. Zarra
10

Na dobry początek musisz zdecydować, co chcesz i nie chcesz akceptować jako adresu e-mail?

99% adresów e-mail wygląda tak: [email protected] lub [email protected]

Jednak posiadanie takiego adresu e-mail jak ten jest technicznie legalne: f !#$%&'*+-/=?^_{|} ~ "ha!" @ Com

Prawdopodobnie na świecie jest tylko kilka prawidłowych wiadomości e-mail dla domen najwyższego poziomu i prawie nikt nie używa większości tych innych znaków (zwłaszcza cudzysłowów i odwrotnych apostrofów), więc możesz założyć, że są to nieprawidłowe rzeczy do zrobienia. Ale powinieneś to zrobić jako świadomy wybór.

Poza tym zrób to, co mówi Paweł i spróbuj dopasować dane wejściowe do wyrażenia regularnego, takiego jak to: ^ [A-Z0-9 ._% + -] + @ [A-Z0-9 .-] +. [AZ] { 2,} $

Ten będzie pasował do adresu e-mail prawie każdego.

Brandon Yarbrough
źródło
mimo że ta odpowiedź została napisana w 2009 roku, nadal pojawia się bardzo wysoko w wynikach wyszukiwania. chciałem tylko dodać, że to nie jest już aktualne, a powyższe wyrażenie regularne jest nieco restrykcyjne. na przykład teraz możesz mieć 4-cyfrową lub więcej domenę najwyższego poziomu
Jack
Słuszna uwaga, zmieniono go na „co najmniej 2 cyfry”. Jeśli chcesz, możesz dalej edytować.
Brandon Yarbrough
7

Chociaż skupienie się na wyrażeniach regularnych jest dobre, to jest to tylko pierwszy i konieczny krok. Istnieją inne kroki, które również należy uwzględnić, aby stworzyć dobrą strategię walidacji.

Dwie rzeczy nad moją głową to:

  1. Sprawdzanie poprawności DNS, aby upewnić się, że domena rzeczywiście istnieje.

  2. Po sprawdzeniu poprawności dns możesz również wybrać walidację smtp. wyślij wywołanie do serwera smtp, aby sprawdzić, czy użytkownik faktycznie istnieje.

W ten sposób możesz wyłapać wszelkiego rodzaju błędy użytkownika i upewnić się, że jest to prawidłowy adres e-mail.

Srikar Doddi
źródło
7

Ta funkcja jest prosta, a mimo to dokładniej sprawdza adres e-mail. Na przykład, zgodnie z RFC2822, adres e-mail nie może zawierać dwóch kropek z rzędu, np. Imię..nazwisko @ domena..com

Ważne jest również, aby używać kotwic w wyrażeniach regularnych, jak widać w tej funkcji. Bez kotwic następujący adres e-mail jest uważany za prawidłowy: imię; imię) [email protected] (bla, ponieważ sekcja [email protected] jest prawidłowa, ignorując imię; imię) na początku i (bla na końcu. Kotwice wymuszają mechanizm wyrażeń regularnych do weryfikacji całej wiadomości e-mail.

Ta funkcja korzysta z NSPredicate, które nie istnieje w iOS 2. Niestety może nie pomóc pytającemu, ale miejmy nadzieję, że pomoże innym z nowszymi wersjami iOS. Jednak wyrażenia regularne w tej funkcji można nadal zastosować do RegExKitLite w systemie iOS 2. W przypadku użytkowników korzystających z systemu iOS 4 lub nowszego te wyrażenia regularne można zaimplementować za pomocą NSRegularExpression.

- (BOOL)isValidEmail:(NSString *)email
{
    NSString *regex1 = @"\\A[a-z0-9]+([-._][a-z0-9]+)*@([a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,4}\\z";
    NSString *regex2 = @"^(?=.{1,64}@.{4,64}$)(?=.{6,100}$).*";
    NSPredicate *test1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex1];
    NSPredicate *test2 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex2];
    return [test1 evaluateWithObject:email] && [test2 evaluateWithObject:email];
}

Zobacz sprawdzanie poprawności adresu e-mail przy użyciu wyrażenia regularnego w Objective-C .

Maniak
źródło
iOS 2.0 nie miał NSPredicate.
Marcus S. Zarra
2
Ale jaki jest pożytek z tego pytania i jaki jest pożytek z ios 2. Mamy najnowszy system operacyjny, czyli ios 7.1. możesz też użyć ios 6.
Gaurav Gilani
6
NSString *emailString = textField.text; **// storing the entered email in a string.** 
**// Regular expression to checl the email format.** 
NSString *emailReg = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; 
NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",emailReg]; 
if (([emailTest evaluateWithObject:emailString] != YES) || [emailStringisEqualToString:@""]) 
{ 
UIAlertView *loginalert = [[UIAlertView alloc] initWithTitle:@" Enter Email in" message:@"[email protected] format" delegate:self 
cancelButtonTitle:@"OK" otherButtonTitles:nil]; 

enter code here

[loginalert show]; 
[loginalert release]; 
} 
If email is invalid, it will remind the user with an alert box. 
Hope this might be helpful for you all. 
hirak
źródło
4

Zauważyłem, że użycie wyrażenia regularnego działa całkiem nieźle w celu weryfikacji adresu e-mail.

Główną wadą wyrażeń regularnych jest oczywiście łatwość konserwacji, więc komentuj, jakich nigdy wcześniej nie komentowałeś. Obiecuję ci, jeśli tego nie zrobisz, będziesz żałował, że tak się nie stało, gdy wrócisz do wyrażenia po kilku tygodniach.

Oto link do dobrego źródła, http://www.regular-expressions.info/email.html .

Paul Redman
źródło
Niedawno zaimplementowałem przedostatnią wersję na tej stronie i jestem z niej całkiem zadowolony. Działa dobrze w przypadku prostego adresu e-mail [email protected], bez cudzysłowów ani nawiasów dla pełnej nazwy. Świetnie sprawdza się w przypadku walidacji formularzy internetowych, gdzie ludzie i tak nie będą wpisywać tego typu rzeczy.
zombat
2
Biedni ludzie z ich domeną TLD .museum.
BadPirate
3

Kopiąc brud, ale właśnie natknąłem się na SHEmailValidator, który wykonuje doskonałą robotę i ma ładny interfejs.

Cyrille
źródło
To pytanie było specyficzne dla iOS 2.0, który nie miał NSPredicate lub całego szeregu innych rzeczy, które są używane w tej bibliotece.
Marcus S. Zarra
1
Wiem, ale wylądowałem tutaj jako pierwszy podczas wyszukiwania hasła „weryfikacja adresu e-mail w systemie ios”. Może w przyszłości ja przeprowadzę to samo poszukiwanie i wyląduję tutaj, a to zaoszczędzi mu trochę czasu.
Cyrille
1

Wiele witryn internetowych udostępnia wyrażenia regularne, ale dobrze byłoby je poznać i zrozumieć, a także sprawdzić, czy to, co chcesz, spełnia Twoje potrzeby w oficjalnym RFC dla formatów adresów e-mail.

W nauce RegEx języki interpretowane mogą być dużym uproszczeniem i podstawą do testów. Rubular jest oparty na Rubim, ale jest dobrym sposobem na szybkie przetestowanie i zweryfikowanie: http://www.rubular.com/

Poza tym kup najnowsze wydanie książki O'Reilly Mastering Regular Expressions. Będziesz chciał poświęcić czas na zrozumienie pierwszych 3 lub 4 rozdziałów. Wszystko po tym będzie polegało na budowaniu wiedzy na temat wysoce zoptymalizowanego użycia RegEx.

Często serie mniejszych, łatwiejszych w zarządzaniu wyrażeń regularnych są łatwiejsze do utrzymania i debugowania.

user656483
źródło
0

Oto rozszerzenie String, które sprawdza poprawność wiadomości e-mail w Swift.

extension String {

    func isValidEmail() -> Bool {
        let stricterFilter = false
        let stricterFilterString = "^[A-Z0-9a-z\\._%+-]+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$"
        let laxString = "^.+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2}[A-Za-z]*$"
        let emailRegex = stricterFilter ? stricterFilterString : laxString
        let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
        return emailTest.evaluate(with: self)
    }
}

Skopiowano z odpowiedzi do: Sprawdź, czy adres e-mail jest prawidłowy na iOS

InnisBrendan
źródło
Na NSPredicateiOS 2.0 nie było
Marcus S. Zarra
-2

Nie powinieneś próbować używać wyrażenia regularnego do sprawdzania poprawności wiadomości e-mail. Przy ciągle zmieniających się TLD Twój walidator jest niekompletny lub niedokładny. Zamiast tego powinieneś wykorzystać NSDataDetectorbiblioteki Apple, które wezmą ciąg i spróbują sprawdzić, czy są jakieś znane pola danych (e-maile, adresy, daty itp.). Apple SDK wykona ciężki wysiłek, aby być na bieżąco z domenami TLD, a Ty możesz odciążyć się od ich wysiłków !! :)

Ponadto, jeśli iMessage (lub jakiekolwiek inne pole tekstowe) nie uważa, że ​​to e-mail, czy powinieneś rozważyć e-mail?

Umieściłem tę funkcję w NSStringkategorii, więc testowany przez ciebie ciąg jest self.

- (BOOL)isValidEmail {
    // Trim whitespace first
    NSString *trimmedText = [self stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
    if (self && self.length > 0) return NO;

    NSError *error = nil;
    NSDataDetector *dataDetector = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:&error];
    if (!dataDetector) return NO;

    // This string is a valid email only if iOS detects a mailto link out of the full string
    NSArray<NSTextCheckingResult *> *allMatches = [dataDetector matchesInString:trimmedText options:kNilOptions range:NSMakeRange(0, trimmedText.length)];
    if (error) return NO;
    return (allMatches.count == 1 && [[[allMatches.firstObject URL] absoluteString] isEqual:[NSString stringWithFormat:@"mailto:%@", self]]);
}

lub jako szybkie Stringrozszerzenie

extension String {
    func isValidEmail() -> Bool {
        let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty, let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
            return false
        }
        let allMatches = dataDetector.matches(in: trimmed, options: [], range: NSMakeRange(0, trimmed.characters.count))

        return allMatches.count == 1 && allMatches.first?.url?.absoluteString == "mailto:\(trimmed)"
    }
}
Pan T.
źródło
1
To pytanie pochodzi z OSIEM lat temu.
Marcus S. Zarra
1
A jednak, jeśli wy Google validate email objective-c, to pytanie jest trzecim wynikiem. Niektóre rzeczy w Internecie nie starzeją się. :-)
Craig Otis,
1
Przestań spamować linkami do tej odpowiedzi pod każdym znalezionym postem dotyczącym sprawdzania poprawności adresów e-mail. Komentarze służą do prośby o wyjaśnienie, a nie do spamowania linków do Twoich odpowiedzi.
meagar
Przy okazji, NSDataDetectorNIE istniał w iOS 2.0, o co chodziło / dotyczy tego pytania.
Marcus S. Zarra
-7
// Method Call
NSString *email = @"Your Email string..";

BOOL temp = [self validateEmail:email];

if(temp)
{
// Valid
}
else
{
// Not Valid
}
// Method description

- (BOOL) validateEmail: (NSString *) email {
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    BOOL isValid = [emailTest evaluateWithObject:email];
    return isValid;
}
Gaurav Gilani
źródło
3
Ten wątek / pytanie dotyczy iOS 2. NSPredicatenie istniał w iOS 2; został dodany dopiero w iOS 3.
Marcus S. Zarra
3
Odpowiedziałem, ponieważ twoja odpowiedź jest błędna. Pytanie brzmi „jak zrobić X na iOS Y” i odpowiedziałeś za pomocą frameworka, którego nie ma w tej wersji iOS.
Marcus S. Zarra