Como validar um endereço de email rapidamente?

338

Alguém sabe como validar um endereço de email no Swift? Encontrei 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;
    }
}

mas não posso traduzi-lo para Swift.

Giorgio Nocera
fonte
8
a tradução deve ser direta. que parte está lhe dando problemas?
Sulthan
12
Não se esqueça de orar para que nenhum de seus usuários tenha um dos novos domínios de nível superior. Por exemplo.coffee
Matthias Bauch 8/15
11
@ Antzi: Eu verifiquei com "someone @ gmail" e seu regex retornou verdadeiro.
Đông Um
2
As expressões regulares não funcionam para validar que os usuários digitaram seu endereço de email. A única maneira 100% correta é enviar um email de ativação. Veja: eu sabia como para validar um endereço de email até que eu li O RFC
mouviciel
2
Este é um controle de qualidade fascinante. É quase certamente o controle de qualidade "mais errado" em todo o site. A resposta atualmente nº 1 com 600 votos (o quê ?!) está absolutamente, totalmente errada de todas as maneiras possíveis (todas as linhas individuais estão completamente erradas e todos os conceitos e idéias estão errados ... !!!) !!! Muitas das outras respostas altamente votadas são "completamente erradas", "extremamente depreciativas" ou simplesmente quebradas e nem sequer compilam. Além disso, embora a natureza deste Q exija "engenharia de regex de elite", muitas respostas (altamente votadas!) Apresentam uma engenharia de regex terrível. É um controle de qualidade realmente interessante !! Por quê??
Gordo

Respostas:

769

Eu usaria 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 versões do Swift anteriores à 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 versões do Swift anteriores à 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
fonte
6
não return emailTest.evaluateWithObject(testStr)seria muito mais simples e legível? Comparando com == trueé um pouco como Javascript.
Sulthan
15
Ele não verifica se existe uma extensão disponível, um @ a já está OK :(
CularBytes
6
isso não valida para test @ test ... com #
Alan Alan
3
Isso não detecta o email. @ Invalid.com ou o email @ .invalid.com. A resposta abaixo de @alexcristea does
Ben Sullivan
3
É muito engraçado que ............ assim como (1) o regex esteja totalmente incorreto (2), o regex (mesmo dentro do contexto do que está tentando fazer) tem grandes erros ( 3) o Swift está errado (4), mesmo deixando isso de lado, o estilo está totalmente errado (5) não que isso importe, dado todo o resto, mas nem sequer menciona que você precisa armazenar em cache o predicado ... com humor, ( 6) ainda resta um código ("calendário" - o quê?) De onde ele foi copiado.
Fattie
115

Edição, atualizada para o 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)

}

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

}

Está funcionando bem.

Azik Abdullah
fonte
2
o primeiro com um regex válido. os outros validam aa @ aach para true #
netshark1000 #
11
@ netshark1000, apenas com votos positivos, qualquer resposta estará no topo. :)
Azik Abdullah
NSRegularExpression é mais simples de usar do que NSPredicate
Guillaume Laurent
11
Ele não trata da condição de dois pontos após o nome do domínio. tente esta resposta stackoverflow.com/a/53441176/5032981
Prashant Gaikwad
@AzikAbdullah Se você digitar 'abc @ gmail..com' então também irá validar
Nij
110

Como uma Stringextensão de 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() {

}
Arsonik
fonte
4
countElementsé agoracount
Zack Shapiro
25
xxx @ yyy retornar verdadeiro?
Cullen SUN
11
O mesmo que Cullen SUN, foo @ bar retorna true.
Rémy Virin
3
user @ host sem .tld também é um endereço de e-mail válido, por exemplo, root @ localhost
quarta
11
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus
64

Se você está procurando uma solução limpa e simples para fazer isso, consulte https://github.com/nsagora/validation-components .

Ele contém um predicado de validação de email que é fácil de integrar no seu código:

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

Por trás do capô, ele usa o 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
fonte
3
Uau, não sabia sobre emailregex.com. Isso é incrível!
Samuel Ev 11/11
2
Finalmente, um que filtre o email. @. Email.com #
Ben Sullivan
está trabalhando com exatamente - [email protected]. não é validar abc @ abc
Anil Gupta
Ah, finalmente ..: D
Ümañg ßürmån
39

Aqui está a solução razoável:

"A SOLUÇÃO RAZOÁVEL"

Usado e testado por anos em muitos aplicativos de grande volume.

1 - evita os muitos erros terríveis de regex que você costuma ver nessas sugestões

2 - NÃO permite e-mails estúpidos como "x @ x" que são considerados válidos sob certas RFCs, mas são completamente bobos, não podem ser usados ​​como e-mails e que sua equipe de suporte rejeitaria instantaneamente e que todos serviços de mala direta (mailchimp, google, aws, etc) simplesmente rejeitam. Se (por algum motivo) você precisar de uma solução que permita seqüências de caracteres como 'x @ x', use outra solução.

3 - o código é muito, muito, muito compreensível

4 - é KISS, confiável e testado para destruição em aplicativos comerciais com um grande número de usuários

5 - um ponto técnico, o predicado é global, como a Apple diz que deveria ser (cuidado com as sugestões de código que não possuem isso)

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

É tão fácil.

Explicação:

Na descrição a seguir, "OC" significa caractere comum - uma letra ou um dígito.

__primeira parte ... tem que começar e terminar com um OC. Para os caracteres no meio, você pode ter certos caracteres, como sublinhado, mas o início e o fim precisam ser um OC. (No entanto, é ok para ter apenas um OC e é isso, por exemplo: [email protected])

__serverpart ... Você tem seções como "blá". que se repetem . (Portanto, o tipo mail.city.fcu.edu.) As seções precisam começar e terminar com um OC, mas no meio você também pode ter um traço "-". (Se você quiser permitir outros caracteres incomuns, talvez o sublinhado, basta adicionar antes do traço.) Não há problema em ter uma seção que seja apenas um OC. (Como em [email protected]) Você pode ter até cinco seções, precisa ter uma. Finalmente, o TLD (como .com) tem tamanho estritamente de 2 a 8. Obviamente, basta alterar esse "8" conforme preferir pelo seu departamento de suporte.


IMPORTANTE!

Você deve manter o predicado como global, não o construa sempre.

Observe que essa é a primeira coisa que a Apple menciona sobre todo o problema nos documentos.

É muito surpreendente quando você vê sugestões que não armazenam em cache o predicado.

Fattie
fonte
11
Ele suporta novos TLDs como .engineer?
Roman
oi @Roman - observe onde claramente diz "Finalmente, o TLD (.com ou similares) é estritamente de 2 a 8 letras". Isso cuida disso. Você pode alterar o "8" para um valor que preferir. (Por agora, em muitas grandes empresas, serviço ao cliente irá simplesmente rejeitar quaisquer longos TLDs como apenas uma farsa - mas de qualquer maneira, é sua decisão, o uso de "8" ou qualquer valor que você gosta.)
Fattie
2
Com relação ao ponto (4): como você testou com muitos usuários? Você acompanhou os usuários que não puderam se inscrever nos aplicativos comerciais, porque a regex os impediu de usar o endereço de email? O único "razoável" deve ser o que a especificação (RFC) especifica ou, se isso não puder ser alcançado, algo mais descontraído, mas que cobre tudo da especificação. Se os usuários não tiverem permissão para digitar x @ x, digitarão [email protected] que passará seu / qualquer regex.
Thetrutz
oi @ thetrutz, "[email protected]" é um endereço de e-mail totalmente normal. o RFC inclui idiotice teórica como "x @ x". qualquer cliente comercial real em que você ou eu trabalhemos dirá "não permitir". (observe que em qualquer empresa de grande porte do mundo real, existem muito mais restrições do que o meu esboço aqui, como mencionei no comentário acima a Roman.) Sua frase final é confusa - é claro que um "e-mail que não funciona" passará teste local? O que você quer dizer? Obviamente, os e-mails são verificados apenas através dos sistemas "confirmar seu e-mail".
Fattie
No Swift, é necessário otimizar todos os processos, porque geralmente usamos esse idioma no lado do servidor.
Nicolas Manzini
25

Aqui está um fusível das duas respostas mais votadas com o regex correto: uma extensão String usando predicado para que você possa chamar 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
fonte
19

Maneira mais simples no 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)
    }
}

Exemplo

"[email protected]".isValidEmail

retorna ...

true
Ken Mueller
fonte
2
qual é o sentido de repetir a resposta repetida? que não depende de nenhum recurso do Swift 5
rommex 10/03
17

Eu sugeriria usá-lo como uma extensão 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
    }
}

E para usá-lo:

if "[email protected]".isEmail { // true
    print("Hold the Door")
}
JeffersonBe
fonte
11
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus
Atualização Swift 4: extensão String {public var isEmail: Bool {deixe dataDetector = try? NSDataDetector (tipos: NSTextCheckingResult.CheckingType.link.rawValue) permite que firstMatch = dataDetector? .FirstMatch (in: self, opções: NSRegularExpression.MatchingOptions.reportCompletion, range: NSRange (local: 0, comprimento: count)) retorne (firstMatch ?. range.location! = NSNotFound && firstMatch? .url? .scheme == "mailto")}
Duan Nguyen
15

Esta é a versão atualizada do 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
fonte
8
foo @ bar retorna verdadeiro ?!
Rémy Virin
2
valida aa @ aach a verdade
netshark1000
4
Isso porque o RFC valida esses endereços de e-mail para true;)
dulgan
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus
é realmente errado / ruim não armazenar em cache o predicado. é a primeira coisa que a Apple diz sobre o problema no documento. um erro flagrante cometido pela maioria das respostas na página.
Fattie # 15/18
9

Há muitas respostas corretas aqui, mas muitas das "expressões regulares" estão incompletas e pode acontecer que um email como: "name @ domain" resulte em um email válido, mas não é. Aqui a solução 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
fonte
não funciona corretamente, permite adicionar espaços após o domínio.
Juan Boero 14/03
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus
@Fattie discute sua afirmação. Seu comentário é muito inútil, sugira uma melhoria, proponha uma correção. Dizendo completamente errado é muito estúpido e subjaz uma mentalidade estreita
Andrea.Ferrando
"Há um monte de respostas aqui mesmo" que a sentença é espetacularmente errada :) :)
Fattie
8

Aqui está um método baseado em 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: tamanho atualizado do TLD.

Aqui está o RegEx definitivo para email, de acordo com a RFC 5322, observe que isso não é melhor usado porque verifica apenas a sintaxe básica dos endereços de email e não verifica se o domínio de nível superior existe.

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

Consulte Regular-Expressions.info para obter informações mais completas sobre o RegExs por email.

Observe que não há escape conforme exigido por um idioma como Objective-C ou Swift.

zaph
fonte
11
o emailRegEx que você usa está completamente errado. Permite apenas TLDs com 2 a 4 caracteres, enquanto domínios como .engineerexistem.
Antzi
Entendido, não estou defendendo minha resposta, mas o nível da edição. Adicione um comentário como acima, faça voto negativo, aponte para uma resposta melhor e adicione sua própria resposta. Não é apropriado alterar substancialmente uma resposta. Eu adicionei o RegEx difusivo para completar.
Zaph
Por que, oh, por que não excluir a resposta então? Que possível motivo poderia haver para mantê-lo aqui?
Fattie
7

Eu prefiro usar uma extensão para isso. Além disso, este URL http://emailregex.com pode ajudá-lo a testar se o regex está correto. De fato, o site oferece implementações diferentes para algumas linguagens de programação. Compartilho minha implementação do 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
fonte
existem alguns problemas .. você pode ter, por exemplo .. blá @ .abc com um ponto estranho lá
Fattie
5

Para swift 2.1: isso funciona corretamente com o 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
        }
    }
}
lee5783
fonte
11
Isso parece funcionar bem para mim. Tanto quanto eu entendo que você mesmo poderia omitir as (letras maiúsculas) 'AZ' desde que você tem a opção .CaseInsensitive definir qualquer maneira ...
AZoM
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus
5

Uso do 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 usado

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

    }
ikbal
fonte
4

Esta é uma nova versão para "A SOLUÇÃO RAZOÁVEL" de @Fattie, testada no Swift 4.1 em um novo arquivo chamado 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)
    }
}

Portanto, seu uso é simples:

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

Simplesmente não gosto de adicionar funca aos Stringobjetos, pois ser um endereço de email é inerente a eles (ou não). Portanto, uma Boolpropriedade se encaixaria melhor que a func, pelo que entendi.

Alejandro Iván
fonte
2

Crie uma extensão simples:

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

Exemplo:

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

Você pode estender seguinte extensão a qualquer coisa que você precisa: isValidPhoneNumber, isValidPasswordetc ...

Bartłomiej Semańczyk
fonte
Observe que a NSRangepropriedade length deve ser usada em String utf16.countvez decharacters.count
Leo Dabus
o padrão está completamente errado
Fattie 23/01
2

No Swift 4.2 e no 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 você deseja usar o 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 chamar função assim ....

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
fonte
1

Eu criei uma biblioteca projetada para validações de entrada e um dos "módulos" permite validar facilmente um monte de coisas ...

Por exemplo, para validar um email:

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

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

SwiftCop é a biblioteca ... espero que ajude!

Andres
fonte
1

Aqui está uma extensão no 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)
    }
}

Apenas use-o assim:

if yourEmailString.isValidEmail() {
    //code for valid email address
} else {
    //code for not valid email address
}
Gefilte Fish
fonte
Mudando para usar o Regex da resposta alexcristea ', é a solução perfeita.
ittgung
0

Como existem tantos nomes de domínio de nível superior estranhos agora, paro de verificar o tamanho do domínio de topo ...

Aqui está o que eu 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)
    } 
}
snowmen10
fonte
0

Parece funcionar também ...

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
fonte
0

Resposta atualizada @Arsonik answer to Swift 2.2, usando código menos detalhado do que outras soluções oferecidas:

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
fonte
abcd @ a está passando com este regex. Você deveria consertar isso.
Gunhan
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus
0

A resposta de @ JeffersonBe é próxima, mas retorna truese a string for "algo que contém algué[email protected] um e-mail válido", que não é o que queremos. A seguir, há uma extensão no String que funciona bem (e permite testar o número de telefone válido e outros detectores de dados para inicializar.

/// 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
fonte
Observe que a propriedade comprimento NSRange deve usar String utf16.count em vez de caracteres. Contagem
Leo Dabus
0

E para o 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
fonte
Observe que a propriedade comprimento NSRange deve usar String utf16.count em vez de caracteres. Contagem
Leo Dabus
0

Minha única adição à lista de respostas seria que, para Linux, NSRegularExpressionnão existe, é realmenteRegularExpression

    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

Isso compila com sucesso no macOS e no Ubuntu.

Andrei Popa
fonte
Observe que a propriedade comprimento NSRange deve usar String utf16.count em vez de caracteres. Contagem
Leo Dabus
0

Melhor solução com melhor 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
fonte
0

Eu gosto de criar extensão

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

Então:

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

Regex perfeito como o Google Email

"^[A-Z0-9a-z][a-zA-Z0-9_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
ami rt
fonte
2
quem votar na minha resposta, verifique seu conhecimento. Eu apliquei esse regex em muitos códigos e meus amigos estão usando esse regex e funciona muito bem. Antes de votar em minha resposta, por favor, comente e deixe-me saber o que há de errado com esse regex.
ami rt
Acho que posso responder: seu regex é simples e não corresponde ao RFC. Por exemplo, os e-mails podem ter aspas e até espaços na primeira parte! Veja haacked.com/archive/2007/08/21/…
Hugal31
11
Desculpe, irmão, acho que você deve verificar a validação de e-mail do google, não há como adicionar espaço na primeira parte de um e-mail, e se meu regex está errado, por que ninguém postou um regex perfeito e de gravação?
ami rt
De acordo com a RFC 5322, "Olá, mundo!" @ Example.com é um email válido. De fato, é quase impossível criar uma regex válida. Nem todo provedor de e-mail se atém à validação de e-mail do Google.
precisa saber é o seguinte
11
É isso que eu quero ouvir e é por isso que mencionei em negrito que o regex acima é como o Google. Obrigado
ami rt
-1

Ou você pode ter uma extensão para o texto opcional do UITextField:

Como usar:

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

extensão:

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
fonte
Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
Leo Dabus