Come convalidare rapidamente un indirizzo e-mail?


338

Qualcuno sa come convalidare un indirizzo e-mail in Swift? Ho trovato questo codice:

- (BOOL) validEmail:(NSString*) emailString {

    if([emailString length]==0){
        return NO;
    }

    NSString *regExPattern = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";

    NSRegularExpression *regEx = [[NSRegularExpression alloc] initWithPattern:regExPattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSUInteger regExMatches = [regEx numberOfMatchesInString:emailString options:0 range:NSMakeRange(0, [emailString length])];

    NSLog(@"%i", regExMatches);
    if (regExMatches == 0) {
        return NO;
    } else {
        return YES;
    }
}

ma non riesco a tradurlo in Swift.


8
la traduzione dovrebbe essere semplice. quale parte ti sta dando problemi?
Sulthan,

12
Non dimenticare di pregare che nessuno dei tuoi utenti abbia uno dei nuovi domini di primo livello. Ad esempio.coffee
Matthias Bauch,

1
@Antzi: ho controllato con "qualcuno @ gmail" e il tuo regex è tornato vero.
Dal

2
Regexes non funziona per la convalida che gli utenti abbiano inserito il proprio indirizzo e-mail. L'unico modo corretto al 100% è di inviare un'e-mail di attivazione. Vedi: sapevo come convalidare un indirizzo e-mail fino a quando non ho letto la RFC
mouviciel,

2
Questo è un affascinante QA. È quasi certamente il QA "più sbagliato" dell'intero sito. La risposta attualmente n. 1 con 600 voti (cosa ?!) è assolutamente, totalmente, sbagliata in ogni modo possibile (ogni singola riga è completamente sbagliata e ogni concetto e idea sono sbagliati ........ !!!) Molte delle altre risposte molto votate sono o "completamente sbagliate", "estremamente scadenti" o, chiaramente, rotte e nemmeno compilate. Inoltre, mentre la natura di questa Q richiede "ingegneria regex d'élite" molte risposte (altamente votate!) Sono caratterizzate da un'ingegnosa ingegneria regex. È un QA davvero interessante !! Perché??
Fattie,

Risposte:


769

Vorrei usare NSPredicate:

func isValidEmail(_ email: String) -> Bool {        
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"

    let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
    return emailPred.evaluate(with: email)
}

per versioni di Swift precedenti alla 3.0:

func isValidEmail(email: String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"

    let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
    return emailPred.evaluate(with: email)
}

per versioni di Swift precedenti alla 1.2:

func isValidEmail(email: String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"

    if let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx) {
        return emailPred.evaluateWithObject(email)
    }
    return false
}

6
non return emailTest.evaluateWithObject(testStr)sarebbe molto più semplice e leggibile? Il confronto con == trueè un po 'come Javascript.
Sulthan,

15
Non verifica se è disponibile un'estensione, a @ a è già OK :(
CularBytes

6
questo non è valido per test @ test ... com
Alan

3
Questo non rileva email. @ Invalid.com o email @ .invalid.com. La risposta che segue da @alexcristea fa
Ben Sullivan,

3
È abbastanza divertente che ............ così come (1) la regex sia totalmente errata (2) la regex (anche nel contesto di ciò che sta cercando di fare) presenta errori importanti ( 3) Swift ha torto (4) anche a parte questo, lo stile è totalmente sbagliato (5) non è importante dato tutto il resto ma non menziona nemmeno che devi memorizzare nella cache il predicato ... umoristicamente, ( 6) c'è ancora codice rimanente ("calendario" - cosa?) Da qualsiasi luogo sia stato copiato.
Fattie

115

Modifica, aggiornata per Swift 3:

func validateEmail(enteredEmail:String) -> Bool {

    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluate(with: enteredEmail)

}

Risposta originale per Swift 2:

func validateEmail(enteredEmail:String) -> Bool {

    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluateWithObject(enteredEmail)

}

Funziona bene.


2
il primo con una regex valida. gli altri convalidano aa @ aach su true
netshark1000 il

1
@ netshark1000, solo con voti positivi, ogni risposta sarà in cima. :)
Azik Abdullah

NSRegularExpression è più semplice da usare rispetto a NSPredicate
Guillaume Laurent

1
Non gestisce la condizione dei due punti dopo il nome del dominio. prova questa risposta stackoverflow.com/a/53441176/5032981
Prashant Gaikwad

@AzikAbdullah Se si immette "abc @ gmail..com", verrà convalidato anche
Nij

110

Come Stringestensione di classe

SWIFT 4

extension String {
    func isValidEmail() -> Bool {
        // here, `try!` will always succeed because the pattern is valid
        let regex = try! NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
        return regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: count)) != nil
    }
}

uso

if "rdfsdsfsdfsd".isValidEmail() {

}

4
countElementsè oracount
Zack Shapiro,

25
xxx @ yyy return true?
Cullen SUN,

1
Come Cullen SUN, foo @ bar ritorna vero.
Rémy Virin,

3
user @ host senza .tld è anche un indirizzo e-mail valido, ad esempio root @ localhost
mer

1
Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

64

Se stai cercando una soluzione pulita e semplice per farlo, dai un'occhiata a https://github.com/nsagora/validation-components .

Contiene un predicato di convalida dell'email che è facile da integrare nel codice:

let email = "test@example.com"
let rule = EmailValidationPredicate()
let isValidEmail = rule.evaluate(with: email)

Dietro il cofano utilizza RFC 5322 reg ex ( http://emailregex.com ):

let regex = "(?:[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}~-]+(?:\\.[\\p{L}0-9!#$%\\&'*+/=?\\^_`{|}" +
    "~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" +
    "x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\p{L}0-9](?:[a-" +
    "z0-9-]*[\\p{L}0-9])?\\.)+[\\p{L}0-9](?:[\\p{L}0-9-]*[\\p{L}0-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]?|[\\p{L}0-9-]*[\\p{L}0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21" +
    "-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"

3
Wow, non sapevo di emailregex.com. È fantastico!
Samuel Ev,

2
Infine, uno che filtra la posta elettronica. @. Email.com
Ben Sullivan,

sta funzionando con esatto - abcd@abcd.com. non è valido abc @ abc
Anil Gupta,

Ah, finalmente ..: D
Ümañg ßürmån,

39

Ecco la soluzione ragionevole:

"LA SOLUZIONE RAGIONEVOLE"

Utilizzato e testato per anni in molte app di grandi volumi.

1 - evita i molti terribili errori regex che vedi spesso in questi suggerimenti

2 - NON consente e-mail stupide come "x @ x" che si ritiene siano valide in determinati RFC, ma sono completamente stupide, non possono essere utilizzate come e-mail e che il personale di supporto rifiuterà all'istante, e che tutti i servizi di mailer (mailchimp, google, aws, ecc.) semplicemente rifiutano. Se (per qualche motivo) hai bisogno di una soluzione che consenta stringhe come 'x @ x', usa un'altra soluzione.

3 - il codice è molto, molto, molto comprensibile

4 - è KISS, affidabile e testato fino alla distruzione su app commerciali con un numero enorme di utenti

5 - un punto tecnico, il predicato è un globale, come Apple dice che dovrebbe essere (attenzione ai suggerimenti di codice che non hanno questo)

let __firstpart = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?"
let __serverpart = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}"
let __emailRegex = __firstpart + "@" + __serverpart + "[A-Za-z]{2,8}"
let __emailPredicate = NSPredicate(format: "SELF MATCHES %@", __emailRegex)

extension String {
    func isEmail() -> Bool {
        return __emailPredicate.evaluate(with: self)
    }
}

extension UITextField {
    func isEmail() -> Bool {
        return self.text!.isEmail()
    }
}

È così facile

Spiegazione:

Nella seguente descrizione, "OC" significa carattere ordinario - una lettera o una cifra.

__firstpart ... deve iniziare e terminare con un OC. Per i personaggi nel mezzo puoi avere alcuni caratteri come il trattino basso, ma l' inizio e la fine devono essere un OC. (Tuttavia, va bene avere un solo OC e basta, ad esempio: j@blah.com)

__serverpart ... Hai sezioni come "blah". quale ripetere . (Quindi tipo di cosa mail.city.fcu.edu.) Le sezioni devono iniziare e terminare con un OC, ma al centro puoi anche avere un trattino "-". (Se vuoi consentire altri caratteri insoliti lì dentro, forse il trattino basso, aggiungi semplicemente prima del trattino.) Va bene avere una sezione che è solo un OC. (Come in joe@w.campus.edu) È possibile avere fino a cinque sezioni, è necessario avere uno. Finalmente il TLD (ad esempio .com) è strettamente 2 a 8 in formato . Ovviamente, cambia semplicemente "8" come preferisci dal tuo dipartimento di supporto.


IMPORTANTE!

È necessario mantenere il predicato come globale, non crearlo ogni volta.

Nota che questa è la prima cosa che Apple menziona sull'intero problema nei documenti.

È molto sorprendente quando vedi suggerimenti che non memorizzano nella cache il predicato.


1
Supporta nuovi TLD come .engineer?
Roman,

ciao @Roman - nota dove dice chiaramente "Finalmente il TLD (.com o simili) è rigorosamente composto da 2 a 8 lettere". Questo se ne occupa. Puoi cambiare "8" con un valore che preferisci. (Per ora, in molte grandi aziende, il servizio clienti rifiuterà semplicemente qualsiasi TLD lungo come una semplice truffa - ma comunque è una tua decisione, usa "8" o qualsiasi valore ti piaccia.)
Fattie,

2
Per quanto riguarda il punto (4): come hai effettuato il test con molti utenti? Hai tracciato gli utenti, che non potevano iscriversi con le app commerciali, perché il regex ha impedito loro di usare il loro indirizzo email? L'unico "ragionevole" dovrebbe essere, cosa specifica la specifica (RFC) o se questo non può essere raggiunto, quindi qualcosa che è più rilassato, ma copre tutto dalla specifica. Se gli utenti non sono autorizzati a inserire x @ x, inseriranno un po 'garbage@example.com che passerà il tuo / qualsiasi regex.
thetrutz,

ciao @thetrutz, "garbage@example.com" è un indirizzo e-mail assolutamente normale. la RFC include idiozia teorica come "x @ x". qualsiasi cliente commerciale per cui tu o io abbia mai lavorato dirà "non consentire quelli". (nota che in ogni grande impresa del mondo reale, ci sono molte più restrizioni rispetto al mio profilo approssimativo qui, come menziono nel commento sopra a Roman.) La tua frase finale è confusa - ovviamente una "email non funzionante" passerà qualsiasi test locale? Cosa intendi? Ovviamente le e-mail vengono verificate solo alla fine attraverso i sistemi "conferma la tua e-mail".
Fattie,

In Swift è necessario ottimizzare ogni processo perché di solito utilizziamo questa lingua sul lato server.
Nicolas Manzini,

25

Ecco una miccia delle due risposte più votate con la regex corretta: un'estensione String che utilizza predicato in modo da poter chiamare string.isEmail

    extension String {
        var isEmail: Bool {
           let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,20}"            
           let emailTest  = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
           return emailTest.evaluateWithObject(self)
        }
    }

19

Il modo più semplice in Swift 5

extension String {
    var isValidEmail: Bool {
        NSPredicate(format: "SELF MATCHES %@", "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}").evaluate(with: self)
    }
}

Esempio

"kenmueller0@gmail.com".isValidEmail

ritorna...

true

2
che senso ha ripetere la risposta ripetuta? che non dipende da nessuna funzionalità di Swift 5
rommex il

17

Suggerirei di usarlo come estensione di String:

extension String {    
    public var isEmail: Bool {
        let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)

        let firstMatch = dataDetector?.firstMatch(in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: length))

        return (firstMatch?.range.location != NSNotFound && firstMatch?.url?.scheme == "mailto")
    }

    public var length: Int {
        return self.characters.count
    }
}

E per usarlo:

if "hodor@gameofthrones.com".isEmail { // true
    print("Hold the Door")
}

1
Nota che la proprietà lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

Aggiorna Swift 4: extension String {public var isEmail: Bool {let dataDetector = try? NSDataDetector (tipi: NSTextCheckingResult.CheckingType.link.rawValue) let firstMatch = dataDetector? .FirstMatch (in: self, opzioni: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange (location: 0, length: count)) return (firstMatch ?. range.location! = NSNotFound && firstMatch? .url? .scheme == "mailto")}
Duan Nguyen

15

Questa è la versione aggiornata di Swift 2.0 - 2.2

 var isEmail: Bool {
    do {
        let regex = try NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .CaseInsensitive)
        return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
    } catch {
        return false
    }
}

8
foo @ bar ritorna vero ?!
Rémy Virin,

2
convalida aa @ aach su true
netshark1000

4
Questo perché RFC convalida questi indirizzi e-mail su true;)
dulgan

Nota che la proprietà lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

è davvero sbagliato / scarso non memorizzare nella cache il predicato. è la prima cosa che Apple dice sul problema nel doco. un errore lampante fatto dalla maggior parte delle risposte sulla pagina.
Fattie,

9

Ci sono molte risposte giuste qui, ma molti dei "regex" sono incompleti e può accadere che un messaggio di posta elettronica come "name @ domain" dia un messaggio di posta elettronica valido, ma non lo è. Ecco la soluzione completa:

extension String {

    var isEmailValid: Bool {
        do {
            let regex = try NSRegularExpression(pattern: "(?:[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])+)\\])", options: .CaseInsensitive)
            return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
        } catch {
            return false
        }
    }
}

non funziona correttamente, ti consente di aggiungere spazi dopo il dominio.
Juan Boero,

Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

@Fattie sostengono la tua affermazione. Il tuo commento è molto inutile, suggerisci un miglioramento, proponi una soluzione. Dire completamente sbagliato è molto stupido e sta alla base di una mentalità molto stretta
Andrea.Ferrando,

"Qui ci sono molte risposte giuste" quella frase è
incredibilmente

8

Ecco un metodo basato su rangeOfString:

class func isValidEmail(testStr:String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let range = testStr.rangeOfString(emailRegEx, options:.RegularExpressionSearch)
    let result = range != nil ? true : false
    return result
}

Nota: lunghezza TLD aggiornata.

Ecco il RegEx definitivo per la posta elettronica come da RFC 5322, nota che questo non è meglio usare perché controlla solo la sintassi di base degli indirizzi e-mail e non controlla se esiste il dominio di livello superiore.

(: [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]) +)
     \])

Vedere Regular-Expressions.info per informazioni più complete sull'e-mail RegExs.

Si noti che non è necessario eseguire la escape come richiesto da un linguaggio come Objective-C o Swift.


1
l'emailRegEx che usi è semplicemente sbagliata. Consentono solo TLD da 2 a 4 caratteri, mentre .engineeresistono domini simili .
Antzi,

Capito, non sto difendendo la mia risposta ma il livello della modifica. Aggiungi un commento come sopra, vota verso il basso, punta a una risposta migliore, aggiungi la tua risposta. Non è opportuno modificare sostanzialmente una risposta. Ho aggiunto il diffusivo RegEx per completezza.
zaph,

Perché oh perché non cancellare la risposta allora? Quale possibile ragione potrebbe esserci per tenerlo qui?
Fattie,

7

Preferisco usare un'estensione per questo. Inoltre, questo URL http://emailregex.com può aiutarti a verificare se regex è corretto. In effetti, il sito offre diverse implementazioni per alcuni linguaggi di programmazione. Condivido la mia implementazione per Swift 3 .

extension String {
    func validateEmail() -> Bool {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
        return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
    }
}

ci sono alcuni problemi .. puoi avere, per esempio .. blah @ .abc con un punto strano lì
Fattie

5

Per swift 2.1: funziona correttamente con l'email foo @ bar

extension String {
    func isValidEmail() -> Bool {
        do {
            let regex = try NSRegularExpression(pattern: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}", options: .CaseInsensitive)
            return regex.firstMatchInString(self, options: NSMatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count)) != nil
        } catch {
                return false
        }
    }
}

1
Questo sembra funzionare bene per me. A quanto ho capito, potresti anche omettere la "AZ" (lettere maiuscole) poiché hai l'opzione .CaseInsensitive impostato comunque ...
AZOM

Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

5

Uso di Swift 4.2

extension String {
    func isValidEmail() -> Bool {
        let regex = try? NSRegularExpression(pattern: "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$", options: .caseInsensitive)
        return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.count)) != nil
    }
    func isValidName() -> Bool{
        let regex = try? NSRegularExpression(pattern: "^[\\p{L}\\.]{2,30}(?: [\\p{L}\\.]{2,30}){0,2}$", options: .caseInsensitive)

        return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.count)) != nil
    } }

E usato

if (textField.text?.isValidEmail())! 
    {
      // bla bla
    }
else 
    {

    }

4

Questa è una nuova versione di "THE REASONABLE SOLUTION" di @Fattie, testata su Swift 4.1 in un nuovo file chiamato String+Email.swift:

import Foundation

extension String {
    private static let __firstpart = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?"
    private static let __serverpart = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}"
    private static let __emailRegex = __firstpart + "@" + __serverpart + "[A-Za-z]{2,6}"

    public var isEmail: Bool {
        let predicate = NSPredicate(format: "SELF MATCHES %@", type(of:self).__emailRegex)
        return predicate.evaluate(with: self)
    }
}

Quindi il suo utilizzo è semplice:

let str = "mail@domain.com"
if str.isEmail {
    print("\(str) is a valid e-mail address")
} else {
    print("\(str) is not a valid e-mail address")
}

Semplicemente non mi piace aggiungere funca agli Stringoggetti, in quanto essere un indirizzo e-mail è inerente a loro (o meno). Quindi una Boolproprietà si adatterebbe meglio di una func, dalla mia comprensione.


2

Crea una semplice estensione:

extension NSRegularExpression {

    convenience init(pattern: String) {
        try! self.init(pattern: pattern, options: [])
    }
}

extension String {

    var isValidEmail: Bool {
        return isMatching(expression: NSRegularExpression(pattern: "^[A-Z0-9a-z\\._%+-]+@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$"))
    }

    //MARK: - Private

    private func isMatching(expression: NSRegularExpression) -> Bool {
        return expression.numberOfMatches(in: self, range: NSRange(location: 0, length: characters.count)) > 0
    }
}

Esempio:

"b@bb.pl".isValidEmail //true
"b@bb".isValidEmail //false

È possibile estendere seguente estensione a tutto il necessario: isValidPhoneNumber, isValidPasswordecc ...


Nota che la NSRangeproprietà length dovrebbe usare al String utf16.countposto dicharacters.count
Leo Dabus il

2

In Swift 4.2 e Xcode 10.1

//Email validation
func isValidEmail(email: String) -> Bool {
    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    var valid = NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: email)
    if valid {
        valid = !email.contains("Invalid email id")
    }
    return valid
}

//Use like this....
let emailTrimmedString = emailTF.text?.trimmingCharacters(in: .whitespaces)
if isValidEmail(email: emailTrimmedString!) == false {
   SharedClass.sharedInstance.alert(view: self, title: "", message: "Please enter valid email")
}

Se si desidera utilizzare SharedClass.

//This is SharedClass
import UIKit
class SharedClass: NSObject {

static let sharedInstance = SharedClass()

//Email validation
func isValidEmail(email: String) -> Bool {
    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    var valid = NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: email)
    if valid {
        valid = !email.contains("Invalid email id")
    }
    return valid
}

private override init() {

}
}

E chiama la funzione in questo modo ....

if SharedClass.sharedInstance. isValidEmail(email: emailTrimmedString!) == false {
   SharedClass.sharedInstance.alert(view: self, title: "", message: "Please enter correct email")
   //Your code here
} else {
   //Code here
}

1

Ho creato una libreria progettata per le convalide di input e uno dei "moduli" consente di convalidare facilmente un sacco di cose ...

Ad esempio per convalidare un'email:

let emailTrial = Trial.Email
let trial = emailTrial.trial()

if(trial(evidence: "test@test.com")) {
   //email is valid
}

SwiftCop è la libreria ... spero che ti aiuti!


1

Ecco un'estensione in Swift 3

extension String {
    func isValidEmail() -> Bool {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: self)
    }
}

Usalo in questo modo:

if yourEmailString.isValidEmail() {
    //code for valid email address
} else {
    //code for not valid email address
}

Cambiando per usare il Regex dalla risposta di alexcristea, è la soluzione perfetta.
ittgung

0

Dal momento che ora ci sono così tanti strani nomi di dominio di primo livello, smetto di controllare la lunghezza del dominio principale ...

Ecco cosa uso:

extension String {

    func isEmail() -> Bool {
        let emailRegEx = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"
        return NSPredicate(format:"SELF MATCHES %@", emailRegEx).evaluateWithObject(self)
    } 
}

0

Sembra funzionare anche ...

let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

func validate(email: String) -> Bool {
    let matches = email.rangeOfString(regex, options: .RegularExpressionSearch)
    if let _ = matches {
        return true
    }
    return false
}

0

Risposta aggiornata alla risposta di @Arsonik a Swift 2.2, utilizzando un codice meno dettagliato rispetto ad altre soluzioni offerte:

extension String {
    func isValidEmail() -> Bool {
        let regex = try? NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .CaseInsensitive)
        return regex?.firstMatchInString(self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
    }
}

abcd @ a sta passando con questo regex. Dovresti risolverlo.
Gunhan,

Nota che la proprietà lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

0

@ La risposta di JeffersonBe è vicina, ma restituisce truese la stringa è "qualcosa che contiene qualcuno@something.com un indirizzo email valido" che non è quello che vogliamo. Di seguito è un'estensione su String che funziona bene (e consente l'avvio di test per phoneNumber valido e altri rilevatori di dati.

/// Helper for various data detector matches.
/// Returns `true` iff the `String` matches the data detector type for the complete string.
func matchesDataDetector(type: NSTextCheckingResult.CheckingType, scheme: String? = nil) -> Bool {
    let dataDetector = try? NSDataDetector(types: type.rawValue)
    guard let firstMatch = dataDetector?.firstMatch(in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange(location: 0, length: length)) else {
        return false
    }
    return firstMatch.range.location != NSNotFound
        // make sure the entire string is an email, not just contains an email
        && firstMatch.range.location == 0
        && firstMatch.range.length == length
        // make sure the link type matches if link scheme
        && (type != .link || scheme == nil || firstMatch.url?.scheme == scheme)
}
/// `true` iff the `String` is an email address in the proper form.
var isEmail: Bool {
    return matchesDataDetector(type: .link, scheme: "mailto")
}
/// `true` iff the `String` is a phone number in the proper form.
var isPhoneNumber: Bool {
    return matchesDataDetector(type: .phoneNumber)
}
/// number of characters in the `String` (required for above).
var length: Int {
    return self.characters.count
}

Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

0

E per Swift 3 :

extension String {
    func isValidEmail() -> Bool {
        let regex = try? NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
        return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.characters.count)) != nil
    }
}

Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

0

La mia unica aggiunta all'elenco delle risposte sarebbe che per Linux, NSRegularExpressionnon esiste, in realtàRegularExpression

    func isEmail() -> Bool {

    let patternNormal = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"

    #if os(Linux)
        let regex = try? RegularExpression(pattern: patternNormal, options: .caseInsensitive)
    #else
        let regex = try? NSRegularExpression(pattern: patternNormal, options: .caseInsensitive)
    #endif

    return regex?.firstMatch(in: self, options: [], range: NSMakeRange(0, self.characters.count)) != nil

Questo viene compilato correttamente su macOS e Ubuntu.


Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus

0

La migliore soluzione con il miglior risultato per

Swift 4.x

 extension String {

        func validateAsEmail() -> Bool {
            let emailRegEx = "(?:[a-zA-Z0-9!#$%\\&‘*+/=?\\^_`{|}~-]+(?:\\.[a-zA-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])+)\\])"

            let emailTest = NSPredicate(format:"SELF MATCHES[c] %@", emailRegEx)
            return emailTest.evaluate(with: self)
        }
    }

0

Mi piace creare l'estensione

   extension String {

func isValidateEmail() -> Bool {
    let emailFormat = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
    let emailPredicate = NSPredicate(format:"SELF MATCHES %@", emailFormat)
    return emailPredicate.evaluate(with: self)
}

}

utilizzo:

if emailid.text!.isValidateEmail() == false(){
 //do what ever you want if string is not matched.

}

0

Swift 5

 func isValidEmailAddress(emailAddressString: String) -> Bool {

 var returnValue = true
 let emailRegEx = "[A-Z0-9a-z.-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,3}"

 do {
        let regex = try NSRegularExpression(pattern: emailRegEx)
        let nsString = emailAddressString as NSString
        let results = regex.matches(in: emailAddressString, range: NSRange(location: 0, length: nsString.length))

        if results.count == 0
        {
            returnValue = false
        }

    } catch let error as NSError {
        print("invalid regex: \(error.localizedDescription)")
        returnValue = false
    }

    return  returnValue
}

Poi:

let validEmail = isValidEmailAddress(emailAddressString: "your@email.com")
print(validEmail)

0

Regex perfetto come Google Email

"^[A-Z0-9a-z][a-zA-Z0-9_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

2
chiunque voti la mia risposta, controlla gentilmente la tua conoscenza. Ho applicato questo regex in molti codici e i miei amici stanno usando questo regex e funziona benissimo. Prima di votare la mia risposta, fai un commento e fammi sapere cosa c'è che non va in questo regex.
ami rt

Penso di poter rispondere: il tuo regex è troppo semplice e non corrisponde alla RFC. Ad esempio, le e-mail possono contenere virgolette e persino spazi nella prima parte! Guarda haacked.com/archive/2007/08/21/…
Hugal31

1
Mi dispiace, fratello, penso che dovresti controllare la convalida dell'email di Google, non c'è modo di aggiungere spazio nella prima parte di un'e-mail, e se la mia regex è sbagliata, allora perché nessuno pubblica post e scrive regex perfetto.
ami rt

Secondo RFC 5322, "Hello world!" @ Example.com è un'e-mail valida. In effetti, è quasi impossibile creare una regex valida. Non tutti i fornitori di posta si attengono alla convalida dell'email di Google.
Hugal31,

1
Questo è quello che voglio ascoltare, ed è per questo che ho citato in grassetto che sopra regex è come Google. Grazie
ami rt

-1

Oppure puoi avere l'estensione per il testo opzionale di UITextField:

come usare:

if  emailTextField.text.isEmailValid() {
      print("email is valid")
}else{
      print("wrong email address")
}

estensione:

extension Optional where Wrapped == String {
    func isEmailValid() -> Bool{
        guard let email = self else { return false }
        let emailPattern = "[A-Za-z-0-9.-_]+@[A-Za-z0-9]+\\.[A-Za-z]{2,3}"
        do{
            let regex = try NSRegularExpression(pattern: emailPattern, options: .caseInsensitive)
            let foundPatters = regex.numberOfMatches(in: email, options: .anchored, range: NSRange(location: 0, length: email.count))
            if foundPatters > 0 {
                return true
            }
        }catch{
            //error
        }
        return false
    }
}

Nota che la proprietà di lunghezza NSRange dovrebbe usare String utf16.count invece di characters.count
Leo Dabus
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.