¿Cómo validar una dirección de correo electrónico en Swift?

338

¿Alguien sabe cómo validar una dirección de correo electrónico en Swift? Encontré este código:

- (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;
    }
}

pero no puedo traducirlo a Swift.

Giorgio Nocera
fuente
8
La traducción debe ser sencilla. ¿Qué parte te está dando problemas?
Sulthan
12
No olvide rezar para que ninguno de sus usuarios tenga uno de los nuevos dominios de nivel superior. Por ejemplo.coffee
Matthias Bauch
1
@Antzi: Lo verifiqué con "alguien @ gmail" y tu expresión regular volvió a ser verdadera.
Anông Un
2
Las expresiones regulares no funcionan para validar que los usuarios hayan ingresado su dirección de correo electrónico. La única forma 100% correcta es enviar un correo electrónico de activación. Ver: Sabía cómo validar una dirección de correo electrónico hasta que
leí el
2
Este es un QA fascinante. Es casi seguro que es el control de calidad "más incorrecto" en todo el sitio. La respuesta n. ° 1 actual con 600 votos (¡¿qué ?!) es absolutamente, totalmente, incorrecta en todas las formas posibles (cada línea individual está completamente equivocada, y cada concepto e idea están equivocados ........ !!!) Muchas de las otras respuestas altamente votadas son "completamente incorrectas", "extremadamente conmovedoras" o simplemente rotas y ni siquiera se compilan. Además, si bien la naturaleza de este Q requiere una "ingeniería de expresiones regulares de élite", muchas respuestas (¡muy votadas!) Presentan una ingeniería de expresiones regulares atroz. ¡Es un control de calidad realmente interesante! ¿¿Por qué??
Fattie

Respuestas:

769

Yo usaría 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)
}

Para versiones de Swift anteriores a la 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)
}

Para versiones de Swift anteriores a 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
}
Maxim Shoustin
fuente
66
¿No return emailTest.evaluateWithObject(testStr)sería mucho más simple y legible? Comparar == truees un poco como Javascript.
Sulthan
15
No comprueba si hay una extensión disponible, a @ a ya está bien :(
CularBytes
66
esto no se valida para test @ test ... com
Alan
3
Esto no detecta el correo electrónico. @ Invalid.com o el correo electrónico @ .invalid.com. La respuesta a continuación de @alexcristea sí
Ben Sullivan
3
Es bastante divertido que ... así como (1) la expresión regular sea completamente incorrecta (2) la expresión regular (incluso en el contexto de lo que está tratando de hacer) tiene errores importantes ( 3) el Swift está equivocado (4) incluso dejando eso de lado, el estilo está totalmente equivocado (5) no es que importe dado todo lo demás, pero ni siquiera menciona que tienes que guardar en caché el predicado ... con humor, ( 6) todavía queda código ("calendario" - ¿qué?) Desde donde se copió.
Fattie
115

Edición, actualizada para 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)

}

Respuesta original para 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)

}

Funciona bien

Azik Abdullah
fuente
2
el primero con una expresión regular válida. los otros validan aa @ aach como verdadero
netshark1000
1
@ netshark1000, solo con votos a favor, cualquier respuesta estará en la parte superior. :)
Azik Abdullah
NSRegularExpression es más fácil de usar que NSPredicate
Guillaume Laurent
1
No maneja la condición de dos puntos después del nombre de dominio. prueba esta respuesta stackoverflow.com/a/53441176/5032981
Prashant Gaikwad el
@AzikAbdullah Si ingresas 'abc @ gmail..com', también se validará
Nij
110

Como una Stringextensión de clase

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() {

}
Arsonik
fuente
44
countElementses ahoracount
Zack Shapiro
25
xxx @ yyy volver cierto?
Cullen SUN
1
Igual que Cullen SUN, foo @ bar regresa verdadero.
Rémy Virin
3
user @ host sin .tld también es una dirección de correo electrónico válida, por ejemplo, root @ localhost
Mié
1
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
64

Si está buscando una solución limpia y simple para hacer esto, debe consultar https://github.com/nsagora/validation-components .

Contiene un predicado de validación de correo electrónico que es fácil de integrar en su código:

let email = "[email protected]"
let rule = EmailValidationPredicate()
let isValidEmail = rule.evaluate(with: email)

Detrás del capó utiliza el 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])+)\\])"
alexcristea
fuente
3
Wow, no sabía sobre emailregex.com. ¡Es asombroso!
Samuel Ev
2
Finalmente, uno que filtra el correo electrónico. @. Email.com
Ben Sullivan
está trabajando con exacto - [email protected]. no es validar abc @ abc
Anil Gupta
Ah, finalmente ..: D
Ümañg ßürmån
39

Aquí está la solución razonable:

"LA SOLUCIÓN RAZONABLE"

Usado y probado durante años en muchas aplicaciones de gran volumen.

1 - evita los muchos errores terribles de expresiones regulares que a menudo ves en estas sugerencias

2 - NO permite correos electrónicos estúpidos como "x @ x" que se consideran válidos bajo ciertos RFC, pero son completamente tontos, no pueden usarse como correos electrónicos, y que su personal de soporte rechazaría instantáneamente, y que todos los servicios de correo (mailchimp, google, aws, etc.) simplemente rechazan. Si (por alguna razón) necesita una solución que permita cadenas como 'x @ x', use otra solución.

3 - el código es muy, muy, muy comprensible

4: es KISS, confiable y probado hasta la destrucción en aplicaciones comerciales con un enorme número de usuarios

5 - un punto técnico, el predicado es global, como Apple dice que debería ser (cuidado con las sugerencias de código que no tienen esto)

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()
    }
}

Es fácil.

Explicación:

En la siguiente descripción, "OC" significa carácter ordinario: una letra o un dígito.

__primera parte ... tiene que comenzar y terminar con un OC. Para los caracteres en el medio , puede tener ciertos caracteres como el subrayado, pero el inicio y el final deben ser un OC. (Sin embargo, está bien tener solo un OC y eso es todo, por ejemplo: [email protected])

__serverpart ... Tienes secciones como "bla". que repiten . (Entonces, el tipo de cosas mail.city.fcu.edu.) Las secciones tienen que comenzar y terminar con un OC, pero en el medio también puede tener un guión "-". (Si desea permitir otros caracteres inusuales allí, quizás el guión bajo, simplemente agregue antes del guión). Está bien tener una sección que sea solo un OC. (Como en [email protected]) Puede tener hasta cinco secciones, debe tener una. Finalmente el TLD (como .com) tiene un tamaño estrictamente de 2 a 8 . Obviamente, simplemente cambie ese "8" según lo prefiera su departamento de soporte.


¡IMPORTANTE!

Debe mantener el predicado como global, no lo construya siempre.

Tenga en cuenta que esto es lo primero que Apple menciona sobre todo el problema en los documentos.

Es muy sorprendente cuando ve sugerencias que no almacenan en caché el predicado.

Fattie
fuente
1
¿Admite nuevos TLD como .engineer?
Romano
hola @Roman: observe dónde dice claramente "Finalmente, el TLD (.com o similar) es estrictamente de 2 a 8 letras". Eso se encarga de eso. Puede cambiar el "8" al valor que prefiera. (Por ahora, en muchas grandes empresas, el servicio al cliente simplemente rechazará cualquier TLD largo como una estafa, pero de todos modos, es su decisión, use "8" o cualquier valor que desee).
Fattie
2
Con respecto al punto (4): ¿cómo lo probó con muchos usuarios? ¿Rastreó a los usuarios que no pudieron registrarse con las aplicaciones comerciales porque la expresión regular les impidió usar su dirección de correo electrónico? Lo único "razonable" debería ser, lo que especifica la especificación (RFC) o si esto no se puede lograr, entonces algo más relajado, pero que abarque todo, desde la especificación. Si los usuarios no pueden ingresar x @ x, ingresarán algo de [email protected] que pasará su / cualquier expresión regular.
thetrutz
hola @thetrutz, "[email protected]" es una dirección de correo electrónico completamente normal. el RFC incluye idiotez teórica como "x @ x". cualquier cliente comercial real para el que usted o yo trabajemos dirá "no permitirlos". (tenga en cuenta que en cualquier gran negocio del mundo real, existen muchas más restricciones que mi bosquejo aquí, como menciono en el comentario anterior a Roman). Su oración final es confusa: por supuesto, un "correo electrónico que no funciona" pasará cualquier prueba local? ¿Qué quieres decir? Obviamente, los correos electrónicos solo se verifican en última instancia a través de los sistemas "confirme su correo electrónico".
Fattie
En Swift existe la necesidad de optimizar cada proceso porque usualmente usamos este lenguaje en el lado del servidor.
Nicolas Manzini
25

Aquí hay un fusible de las dos respuestas más votadas con la expresión regular correcta: una extensión de cadena que usa un predicado para que pueda llamar a 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)
        }
    }
Nicolas Manzini
fuente
19

La forma más sencilla en 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)
    }
}

Ejemplo

"[email protected]".isValidEmail

devoluciones...

true
Ken Mueller
fuente
2
¿Cuál es el punto de repetir la respuesta repetida? que no depende de ninguna característica de Swift 5
rommex
17

Sugeriría usarlo como una extensión de 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
    }
}

Y para usarlo:

if "[email protected]".isEmail { // true
    print("Hold the Door")
}
JeffersonBe
fuente
1
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
Actualización Swift 4: cadena de extensión {public var isEmail: Bool {let dataDetector = try? NSDataDetector (tipos: NSTextCheckingResult.CheckingType.link.rawValue) permite que firstMatch = dataDetector? .FirstMatch (in: self, options: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange (location: 0, length: count)) return (firstMatch ?. range.location! = NSNotFound && firstMatch? .url? .scheme == "mailto")}
Duan Nguyen el
15

Esta es la versión actualizada para 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
    }
}
Joel García Verástica
fuente
8
foo @ bar devuelve cierto?
Rémy Virin
2
valida aa @ aach como verdadero
netshark1000
44
Esto se debe a que el RFC valida estas direcciones de correo electrónico como verdadero;)
dulgan
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
es realmente incorrecto / pobre no almacenar en caché el predicado. Es lo primero que Apple dice sobre el tema en el doco. un error evidente cometido por la mayoría de las respuestas en la página.
Fattie
9

Aquí hay muchas respuestas correctas, pero muchas de las "expresiones regulares" están incompletas y puede suceder que un correo electrónico como: "nombre @ dominio" dé como resultado un correo electrónico válido, pero no lo es. Aquí la solución 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
        }
    }
}
Andrea Ferrando
fuente
no funciona correctamente, le permite agregar espacios después del dominio.
Juan Boero
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
@Fattie discute tu declaración. Su comentario es muy inútil, sugiera una mejora, proponga una solución. Decir completamente mal es muy estúpido y subyace en una mentalidad cercana
Andrea
"Hay muchas respuestas correctas aquí", esa frase es espectacularmente incorrecta :) :)
Fattie
8

Aquí hay un método basado en 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: longitud de TLD actualizada.

Aquí está el RegEx definitivo para el correo electrónico según RFC 5322, tenga en cuenta que es mejor no usarlo porque solo verifica la sintaxis básica de las direcciones de correo electrónico y no verifica si el dominio de nivel superior existe.

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

Consulte Regular-Expressions.info para obtener información más completa sobre RegExs por correo electrónico.

Tenga en cuenta que no debe escapar según lo requiera un lenguaje como Objective-C o Swift.

zaph
fuente
1
el emailRegEx que usa es simplemente incorrecto. Solo permite TLD de 2 a 4 caracteres, mientras que dominios como .engineerexisten.
Antzi
Entendido, no estoy defendiendo mi respuesta, sino el nivel de la edición. Agregue un comentario como el anterior, vote hacia abajo, señale una mejor respuesta, agregue su propia respuesta. No es apropiado cambiar sustancialmente una respuesta. He agregado el RegEx difusivo para completar.
zaph
¿Por qué, por qué no, simplemente borras la respuesta? ¿Qué posible razón podría haber para mantenerlo aquí?
Fattie
7

Prefiero usar una extensión para eso. Además, esta url http://emailregex.com puede ayudarlo a probar si la expresión regular es correcta. De hecho, el sitio ofrece diferentes implementaciones para algunos lenguajes de programación. Comparto mi implementación para 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)
    }
}
Marlon Ruiz
fuente
hay algunos problemas ... puede tener, por ejemplo ... blah @ .abc con un punto extraño allí
Fattie
5

Para swift 2.1: esto funciona correctamente con el correo electrónico 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
        }
    }
}
lee5783
fuente
1
Esto parece funcionar bien para mí. Según tengo entendido, incluso podría omitir la 'AZ' (letras mayúsculas) ya que tiene la opción .CaseInsensitive configurado de todos modos ...
AZOM
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
5

Uso de 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
    } }

Y usado

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

    }
ikbal
fuente
4

Esta es una nueva versión para "LA SOLUCIÓN RAZONABLE" de @Fattie, probada en Swift 4.1 en un nuevo archivo llamado 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)
    }
}

Entonces su uso es simple:

let str = "[email protected]"
if str.isEmail {
    print("\(str) is a valid e-mail address")
} else {
    print("\(str) is not a valid e-mail address")
}

Simplemente no me gusta agregar un funca los Stringobjetos, ya que ser una dirección de correo electrónico es inherente a ellos (o no). Por lo tanto, una Boolpropiedad encajaría mejor que una func, según tengo entendido.

Alejandro Iván
fuente
2

Crear extensión simple:

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
    }
}

Ejemplo:

"[email protected]".isValidEmail //true
"b@bb".isValidEmail //false

Se puede extender siguiente extensión a todo lo que necesita: isValidPhoneNumber, isValidPasswordetc ...

Bartłomiej Semańczyk
fuente
Tenga en cuenta que la NSRangepropiedad de longitud debe usar en String utf16.countlugar decharacters.count
Leo Dabus
el patrón está completamente equivocado
Fattie
2

En Swift 4.2 y 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")
}

Si quieres usar 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() {

}
}

Y llame a una función como esta ...

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

Hice una biblioteca diseñada para validaciones de entrada y uno de los "módulos" le permite validar fácilmente un montón de cosas ...

Por ejemplo para validar un correo electrónico:

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

if(trial(evidence: "[email protected]")) {
   //email is valid
}

SwiftCop es la biblioteca ... ¡espero que ayude!

Andres
fuente
1

Aquí hay una extensión en 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)
    }
}

Solo úsalo así:

if yourEmailString.isValidEmail() {
    //code for valid email address
} else {
    //code for not valid email address
}
Pescado relleno
fuente
Cambiar para usar el Regex de alexcristea 'respuesta, es la solución perfecta.
ittgung
0

Dado que ahora hay tantos nombres de dominio de nivel superior extraños, dejo de verificar la longitud del dominio superior ...

Esto es lo que 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)
    } 
}
muñecos de nieve10
fuente
0

Parece funcionar también ...

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
}
Logicopolis
fuente
0

Respuesta actualizada @Arsonik respuesta a Swift 2.2, usando menos código detallado que otras soluciones ofrecidas:

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
    }
}
Matias Seijas
fuente
abcd @ a está pasando con esta expresión regular. Deberías arreglarlo.
Gunhan
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
0

La respuesta de @ JeffersonBe es cercana, pero devuelve truesi la cadena es "algo que contiene [email protected] un correo electrónico válido", que no es lo que queremos. La siguiente es una extensión en String que funciona bien (y permite probar el número de teléfono válido y otros detectores de datos para arrancar).

/// 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
}
Gujamin
fuente
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
0

Y para 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
    }
}
Danut Pralea
fuente
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
0

Mi única adición a la lista de respuestas sería que para Linux, NSRegularExpressionno existe, en realidad esRegularExpression

    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

Esto se compila con éxito tanto en macOS como en Ubuntu.

Andrei Popa
fuente
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus
0

La mejor solución con el mejor resultado para

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)
        }
    }
Abdelahad Darwish
fuente
0

Me gusta crear extensión

   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)
}

}

uso:

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

}
siva kumar
fuente
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
}

Entonces:

let validEmail = isValidEmailAddress(emailAddressString: "[email protected]")
print(validEmail)
Arafin Russell
fuente
0

Regex perfecto como Google Email

"^[A-Z0-9a-z][a-zA-Z0-9_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
ami rt
fuente
2
Quien vote mi respuesta, compruebe amablemente su conocimiento. He aplicado esta expresión regular en muchos códigos y mis amigos míos están usando esta expresión regular y funciona muy bien. Antes de votar mi respuesta, háganme un comentario y háganme saber qué hay de malo en esta expresión regular.
amrt rt
Creo que puedo responder: su expresión regular es demasiado simple y no coincide con el RFC. Por ejemplo, ¡los correos electrónicos pueden tener citas e incluso espacios en la primera parte! Mira haacked.com/archive/2007/08/21/…
Hugal31
1
Lo siento, hermano, creo que deberías verificar la validación de correo electrónico de Google, no hay forma de agregar espacio en la primera parte de un correo electrónico, y si mi expresión regular es incorrecta, ¿por qué nadie publica una escritura y una expresión regular perfecta?
am rt
Según el RFC 5322, "¡Hola, mundo!" @ Example.com es un correo electrónico válido. De hecho, es casi imposible hacer una expresión regular válida. No todos los proveedores de correo se apegarán a la validación de correo electrónico de Google.
Hugal31
1
Eso es lo que quiero escuchar, y es por eso que mencioné en negrita que la expresión regular anterior es como Google. Gracias
ami rt
-1

O puede tener una extensión para el texto opcional de UITextField:

cómo utilizar:

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

extensión:

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
    }
}
Maciej Chrzastek
fuente
Tenga en cuenta que la propiedad de longitud NSRange debe usar String utf16.count en lugar de characters.count
Leo Dabus