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.


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
}

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.


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

}

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 = "test@example.com"
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])+)\\])"

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 - abcd@abcd.com. 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: j@blah.com)

__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 joe@w.campus.edu) 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.


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 garbage@example.com que passará seu / qualquer regex.
— Thetrutz

oi @ thetrutz, "garbage@example.com" é 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)
        }
    }

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

"kenmueller0@gmail.com".isValidEmail

retorna ...

true

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 "hodor@gameofthrones.com".isEmail { // true
    print("Hold the Door")
}

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

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

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.


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

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

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 
    {

    }

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 = "mail@domain.com"
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.


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:

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

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


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
}

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: "test@test.com")) {
   //email is valid
}

SwiftCop é a biblioteca ... espero que ajude!


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
}

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

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
}

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

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ém@algo.com.com 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
}

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

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.


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

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.

}

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: "your@email.com")
print(validEmail)

0

Regex perfeito como o Google Email

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

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

Note-se que NSRange propriedade de comprimento deve usar cordas utf16.count vez de characters.count
— Leo Dabus
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.